home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-01-30 | 167.8 KB | 4,535 lines |
- --::::::::::
- --types.bdy
- --::::::::::
- -- ***************************************************
- -- * *
- -- * CS_Parts_Types * BODY
- -- * *
- -- ***************************************************
- with Unchecked_Conversion;
- package body CS_Parts_Types is
- --| Notes (none)
-
- function To_Character is new Unchecked_Conversion
- (Source => BYTE, Target => CHARACTER);
-
- function From_Character is new Unchecked_Conversion
- (Source => CHARACTER, Target => BYTE);
-
- -- ...................................................
- -- . .
- -- . CS_Parts_Types.Convert . BODY
- -- . .
- -- ...................................................
- function Convert (Item : in CHARACTER) return BYTE is
- --| Notes (none)
- begin
- return From_Character (Item);
- end Convert;
-
- -- ...................................................
- -- . .
- -- . CS_Parts_Types.Convert . BODY
- -- . .
- -- ...................................................
- function Convert (Item : in INTEGER) return BYTE is
- --| Notes (none)
- I1 : INTEGER := Item;
- I2 : INTEGER := 0;
- begin
- for I in 1..8 loop
- I2 := (I2 * 2) + (I1 - (I1 / 2 * 2));
- I1 := I1/2;
- end loop;
- return BYTE(I2);
- end Convert;
-
- -- ...................................................
- -- . .
- -- . CS_Parts_Types.Convert . BODY
- -- . .
- -- ...................................................
- function Convert (Item : in BYTE) return CHARACTER is
- --| Notes (none)
- CH : CHARACTER;
- begin
- if Item > 127 then
- CH := To_Character (Item - (Item / 128 * 128));
- else
- CH := To_Character (Item);
- end if;
- return CH;
- end Convert;
-
- -- ...................................................
- -- . .
- -- . CS_Parts_Types.Convert . SPEC
- -- . .
- -- ...................................................
- function Convert (Item : in BYTE) return INTEGER is
- --| Notes (none)
- begin
- return INTEGER(Item);
- end Convert;
-
- end CS_Parts_Types;
- --::::::::::
- --console.bdy
- --::::::::::
- -- *********************************************************
- -- * *
- -- * Console * BODY
- -- * *
- -- *********************************************************
- with Text_IO;
- with Unchecked_Conversion;
- package body Console is
- --| Notes (none)
-
- type STATE is (DISABLED, ENABLED);
-
- Output_State : array (1..Max_Number_of_States) of STATE
- := (others => ENABLED);
-
- Current_State : NATURAL := 1;
-
- Terminal : TERMINAL_KIND := TTY;
-
- package INTIO is new TEXT_IO.INTEGER_IO(INTEGER);
- package FLTIO is new TEXT_IO.FLOAT_IO(FLOAT);
-
- function Rend_to_Int is new Unchecked_Conversion (RENDITION,
- INTEGER);
-
- -- .................................................................
- -- . .
- -- . Console.Set_Terminal . BODY
- -- . .
- -- .................................................................
- procedure Set_Terminal (New_Setting : in TERMINAL_KIND := TTY) is
- --| Notes (none)
- begin
- Terminal := New_Setting;
- end Set_Terminal;
-
- -- .................................................................
- -- . .
- -- . Console.Enable_Output . BODY
- -- . .
- -- .................................................................
- procedure Enable_Output is
- --| Notes (none)
- begin
- Output_State(Current_State) := ENABLED;
- end Enable_Output;
-
- -- .................................................................
- -- . .
- -- . Console.Disable_Output . BODY
- -- . .
- -- .................................................................
- procedure Disable_Output is
- --| Notes (none)
- begin
- Output_State(Current_State) := DISABLED;
- end Disable_Output;
-
- -- .................................................................
- -- . .
- -- . Console.Push . BODY
- -- . .
- -- .................................................................
- procedure Push is
- --| Notes (none)
- begin
- if Current_State = Max_Number_of_States then
- raise STATE_OVERFLOW;
- else
- Current_State := Current_State + 1;
- end if;
- end Push;
-
- -- .................................................................
- -- . .
- -- . Console.Pop . BODY
- -- . .
- -- .................................................................
- procedure Pop is
- --| Notes (none)
- begin
- if Current_State = Output_State'FIRST then
- raise STATE_UNDERFLOW;
- else
- Current_State := Current_State - 1;
- end if;
- end Pop;
-
- -- .................................................................
- -- . .
- -- . Console.Position_Cursor . BODY
- -- . .
- -- .................................................................
- procedure Position_Cursor (Row : in ROW_NUMBER;
- Column : in COLUMN_NUMBER) is
- --| Notes (none)
- begin
- if (Terminal /= TTY) and (Output_State(Current_State) = ENABLED) then
- Text_IO.Put (ASCII.ESC & "[");
- INTIO.Put (INTEGER(Row), 0);
- Text_IO.Put (';');
- INTIO.Put (INTEGER(Column), 0);
- Text_IO.Put ('H');
- end if;
- end Position_Cursor;
-
- -- .................................................................
- -- . .
- -- . Console.Erase_Display . BODY
- -- . .
- -- .................................................................
- procedure Erase_Display is
- --| Notes (none)
- begin
- if (Terminal /= TTY) and (Output_State(Current_State) = ENABLED) then
- Text_IO.Put (ASCII.ESC & "[2J");
- end if;
- end Erase_Display;
-
- -- .................................................................
- -- . .
- -- . Console.Erase_Line . BODY
- -- . .
- -- .................................................................
- procedure Erase_Line is
- --| Notes (none)
- begin
- if (Terminal /= TTY) and (Output_State(Current_State) = ENABLED) then
- Text_IO.Put (ASCII.ESC & "[K");
- end if;
- end Erase_Line;
-
- -- .................................................................
- -- . .
- -- . Console.Set_Rendition . BODY
- -- . .
- -- .................................................................
- procedure Set_Rendition (New_Setting : in RENDITION) is
- --| Notes
- --| If the value of Terminal is VT100, no action is taken for any
- --| of the color renditions.
- begin
- if Output_State(Current_State) = ENABLED then
- case New_Setting is
- when ALL_ATTRIBUTES_OFF =>
- if Terminal = ANSI then
- Text_IO.Put (ASCII.ESC & "[0m");
- elsif Terminal = VT100 then
- Text_IO.Put (ASCII.ESC & "[m");
- end if;
- when HIGH_INTENSITY | BLINKING | REVERSE_VIDEO =>
- if Terminal /= TTY then
- Text_IO.Put (ASCII.ESC & "[");
- INTIO.Put (Rend_to_Int(New_Setting), 0);
- Text_IO.Put ('m');
- end if;
- when others =>
- if Terminal = ANSI then
- Text_IO.Put (ASCII.ESC & "[");
- INTIO.Put (Rend_to_Int(New_Setting), 0);
- Text_IO.Put ('m');
- end if;
- end case;
- end if;
- end Set_Rendition;
-
- -- .................................................................
- -- . .
- -- . Console.Put . BODY
- -- . .
- -- .................................................................
- procedure Put (Item : in CHARACTER) is
- --| Notes (none)
- begin
- if Output_State(Current_State) = ENABLED then
- Text_IO.Put (Item);
- end if;
- end Put;
-
- -- .................................................................
- -- . .
- -- . Console.Put . BODY
- -- . .
- -- .................................................................
- procedure Put (Item : in STRING) is
- --| Notes (none)
- begin
- if Output_State(Current_State) = ENABLED then
- Text_IO.Put (Item);
- end if;
- end Put;
-
- -- .................................................................
- -- . .
- -- . Console.Put . BODY
- -- . .
- -- .................................................................
- procedure Put
- ( Item : in STRING;
- Field_Width : in NATURAL;
- On_Overflow : in OVERFLOW_ACTION := TRUNCATE_TAIL;
- On_Underflow : in JUSTIFICATION := LEFT_JUSTIFIED;
- Fill_Char : in CHARACTER := ' ';
- Overflow_Char : in CHARACTER := '*' ) is
- --| Notes (none)
- First_Char : NATURAL := Item'first;
- Last_Char : NATURAL := Item'last;
- Fill_Width : NATURAL;
- begin
- if Output_State(Current_State) = ENABLED then
- if Item'length > Field_Width then
- case On_Overflow is
- when TRUNCATE_TAIL =>
- Last_Char := First_Char + Field_Width - 1;
- Text_IO.Put (Item(First_Char .. Last_Char));
- when TRUNCATE_HEAD =>
- First_Char := Last_Char - Field_Width + 1;
- Text_IO.Put (Item(First_Char .. Last_Char));
- when FILL_WITH_OVERFLOW_CHAR =>
- for I in 1 .. Field_Width loop
- Text_IO.Put (Overflow_Char);
- end loop;
- end case;
- elsif Item'length < Field_Width then
- Fill_Width := Field_Width - Item'length;
- case On_Underflow is
- when LEFT_JUSTIFIED =>
- Text_IO.Put (Item);
- for I in 1 .. Fill_Width loop
- Text_IO.Put (Fill_Char);
- end loop;
- when RIGHT_JUSTIFIED =>
- for I in 1 .. Fill_Width loop
- Text_IO.Put (Fill_Char);
- end loop;
- Text_IO.Put (Item);
- end case;
- else
- Text_IO.Put (Item);
- end if;
- end if;
- end Put;
-
- -- .................................................................
- -- . .
- -- . Console.Put . BODY
- -- . .
- -- .................................................................
- procedure Put (Item : in INTEGER;
- Width : in NATURAL;
- On_Overflow : in NUMERIC_OVERFLOW_ACTION
- := FILL_WITH_OVERFLOW_CHAR;
- Overflow_Char : in CHARACTER := '*') is
- --| Notes (none)
- Overflow : BOOLEAN := FALSE;
- begin
- if Output_State(Current_State) = ENABLED then
- begin
- if Width = 0 then
- Overflow := TRUE;
- else
- if Item < 0 then
- if Item <= -10**(Width-1) then
- Overflow := TRUE;
- end if;
- else
- if Item >= 10**Width then
- Overflow := TRUE;
- end if;
- end if;
- end if;
- exception
- when others =>
- Overflow := FALSE;
- end;
- if not Overflow then
- INTIO.Put (Item, Width);
- else -- Overflow
- case On_Overflow is
- when FILL_WITH_OVERFLOW_CHAR =>
- for I in 1 .. Width loop
- Text_IO.Put (Overflow_Char);
- end loop;
- when OUTPUT_FULL_NUMBER =>
- INTIO.Put (Item, Width);
- end case;
- end if;
- end if;
- end Put;
-
- -- .................................................................
- -- . .
- -- . Console.Put . BODY
- -- . .
- -- .................................................................
- procedure Put (Item : in FLOAT;
- Fore : in NATURAL;
- Aft : in NATURAL;
- On_Overflow : in NUMERIC_OVERFLOW_ACTION
- := FILL_WITH_OVERFLOW_CHAR;
- Overflow_Char : in CHARACTER := '*') is
- --| Notes (none)
- Overflow : BOOLEAN := FALSE;
- begin
- if Output_State(Current_State) = ENABLED then
- begin
- if Fore = 0 then
- Overflow := TRUE;
- else
- if Item < 0.0 then
- if Item <= -10.0**(Fore-1) then
- Overflow := TRUE;
- end if;
- else
- if Item >= 10.0**Fore then
- Overflow := TRUE;
- end if;
- end if;
- end if;
- exception
- when others =>
- Overflow := FALSE;
- end;
- if not Overflow then
- FLTIO.Put (Item, Fore, Aft, 0);
- else -- Overflow
- case On_Overflow is
- when FILL_WITH_OVERFLOW_CHAR =>
- for I in 1 .. Fore loop
- Text_IO.Put (Overflow_Char);
- end loop;
- Text_IO.Put (Overflow_Char); -- decimal
- for I in 1 .. Aft loop
- Text_IO.Put (Overflow_Char);
- end loop;
- when OUTPUT_FULL_NUMBER =>
- FLTIO.Put (Item, Fore, Aft, 0);
- end case;
- end if;
- end if;
- end Put;
-
- -- .................................................................
- -- . .
- -- . Console.Put . BODY
- -- . .
- -- .................................................................
- procedure Put (Item : in FLOAT;
- Fore : in NATURAL := 2;
- Aft : in NATURAL := 2;
- Exp : in NATURAL := 3) is
- --| Notes (none)
- begin
- if Output_State(Current_State) = ENABLED then
- FLTIO.Put (Item, Fore, Aft, Exp);
- end if;
- end Put;
-
- -- .................................................................
- -- . .
- -- . Console.Put_Line . BODY
- -- . .
- -- .................................................................
- procedure Put_Line (Item : in STRING) is
- --| Notes (none)
- begin
- if Output_State(Current_State) = ENABLED then
- Text_IO.Put_Line (Item);
- end if;
- end Put_Line;
-
- -- .................................................................
- -- . .
- -- . Console.New_Line . BODY
- -- . .
- -- .................................................................
- procedure New_Line is
- --| Notes (none)
- begin
- if Output_State(Current_State) = ENABLED then
- Text_IO.New_Line;
- end if;
- end New_Line;
-
- -- .................................................................
- -- . .
- -- . Console.Get . BODY
- -- . .
- -- .................................................................
- procedure Get
- ( Item : out CHARACTER ) is
- --| Notes (none)
- begin -- Get
- Text_IO.Get (Item);
- exception
- when others =>
- raise INPUT_ERROR;
- end Get;
-
- -- .................................................................
- -- . .
- -- . Console.Get . BODY
- -- . .
- -- .................................................................
- procedure Get
- ( Item : out INTEGER ) is
- --| Notes (none)
- begin -- Get
- INTIO.Get (Item);
- exception
- when others =>
- raise INPUT_ERROR;
- end Get;
-
- -- .................................................................
- -- . .
- -- . Console.Get . BODY
- -- . .
- -- .................................................................
- procedure Get
- ( Item : out FLOAT ) is
- --| Notes (none)
- begin -- Get
- FLTIO.Get (Item);
- exception
- when others =>
- raise INPUT_ERROR;
- end Get;
-
- -- .................................................................
- -- . .
- -- . Console.Get_Line . BODY
- -- . .
- -- .................................................................
- procedure Get_Line
- ( Item : out STRING;
- Last : out NATURAL ) is
- --| Notes (none)
- begin -- Get_Line
- Text_IO.Get_Line(Item, Last);
- end Get_Line;
-
- end Console;
- --::::::::::
- --bintree.bdy
- --::::::::::
- with unchecked_deallocation;
-
- Package body Binary_Trees_Pkg is
- --| Efficient implementation of binary trees.
-
-
- ----------------------------------------------------------------------------
- -- Local Operations --
- ----------------------------------------------------------------------------
-
- procedure Free_Node is
- new unchecked_deallocation(Node, Node_Ptr);
-
- procedure Free_Tree is
- new unchecked_deallocation(Tree_Header, Tree);
-
- procedure Free_Iterator is
- new unchecked_deallocation(Iterator_Record, Iterator);
-
- ----------------------------------------------------------------------------
- -- Visible Operations --
- ----------------------------------------------------------------------------
-
- Function Create --| Return an empty tree.
- return Tree is
-
- begin
- return new Tree_Header'(0, Null);
-
- end Create;
-
- ----------------------------------------------------------------------------
-
- Procedure Insert_Node(
- V: Value_Type;
- N: in out Node_Ptr;
- Found: out boolean;
- Duplicate: out Value_Type
- )
- is
- D: integer;
-
- begin
- Found := False;
- if N = null then
- N := new Node'(V, Null, Null);
- else
- D := Difference(V, N.Value);
- if D < 0 then
- Insert_Node(V, N.Less, Found, Duplicate);
- elsif D > 0 then
- Insert_Node(V, N.More, Found, Duplicate);
- else
- Found := True;
- Duplicate := N.Value;
- end if;
- end if;
- end Insert_Node;
-
- Procedure Replace_Node(
- V: Value_Type;
- N: in out Node_Ptr;
- Found: out boolean;
- Duplicate: out Value_Type
- )
- is
- D: integer;
-
- begin
- Found := False;
- if N = null then
- N := new Node'(V, Null, Null);
- else
- D := Difference(V, N.Value);
- if D < 0 then
- Replace_Node(V, N.Less, Found, Duplicate);
- elsif D > 0 then
- Replace_Node(V, N.More, Found, Duplicate);
- else
- Found := True;
- Duplicate := N.Value;
- N.Value := V;
- end if;
- end if;
- end Replace_Node;
-
-
- Procedure Insert( --| Insert a value into a tree.
- V: Value_Type; --| Value to be inserted
- T: Tree --| Tree to contain the new value
- ) --| Raises: Duplicate_Value, Invalid_Tree.
- is
- Found: boolean;
- Duplicate: Value_Type;
-
- begin
- if T = null then
- raise Invalid_Tree;
- end if;
- Insert_Node(V, T.Root, Found, Duplicate);
- if Found then
- raise Duplicate_Value;
- end if;
- T.Count := T.Count + 1;
- end Insert;
-
-
- Procedure Insert_if_not_Found(
- --| Insert a value into a tree, provided a duplicate value is not already there
- V: Value_Type; --| Value to be inserted
- T: Tree; --| Tree to contain the new value
- Found: out boolean;
- Duplicate: out Value_Type
- ) --| Raises: Invalid_Tree.
- is
- was_Found: boolean;
-
- begin
- if T = null then
- raise Invalid_Tree;
- end if;
- Insert_Node(V, T.Root, was_Found, Duplicate);
- Found := was_Found;
- if not was_Found then
- T.Count := T.Count + 1;
- end if;
-
- end Insert_if_Not_Found;
-
- procedure Replace_if_Found(
- --| Replace a value if label exists, otherwise insert it.
- V: Value_Type; --| Value to be inserted
- T: Tree; --| Tree to contain the new value
- Found: out boolean; --| Becomes True iff L already in tree
- Old_Value: out Value_Type --| the duplicate value, if there is one
- ) --| Raises: Invalid_Tree.
-
- is
- was_Found: boolean;
- Duplicate: Value_Type;
-
- begin
- if T = null then
- raise Invalid_Tree;
- end if;
- Replace_Node(V, T.Root, was_Found, Duplicate);
- Found := was_Found;
- if was_Found then
- Old_Value := Duplicate;
- else
- T.Count := T.Count + 1;
- end if;
-
- end Replace_if_Found;
-
- ----------------------------------------------------------------------------
-
- procedure Destroy_Nodes(
- N: in out Node_Ptr
- ) is
- begin
- if N /= null then
- Destroy_Nodes(N.Less);
- Destroy_Nodes(N.More);
- Free_Node(N);
- end if;
- end Destroy_Nodes;
-
- procedure Destroy( --| Free space allocated to a tree.
- T: in out Tree --| The tree to be reclaimed.
- ) is
-
- begin
- if T /= Null then
- Destroy_Nodes(T.Root);
- Free_Tree(T);
- end if;
-
- end Destroy;
-
- ----------------------------------------------------------------------------
-
- procedure Destroy_Deep( --| Free all space allocated to a tree.
- T: in out Tree --| The tree to be reclaimed.
- )
- is
- procedure Destroy_Nodes(
- N: in out node_Ptr
- ) is
- begin
- if N /= null then
- Free_Value(N.Value);
- Destroy_Nodes(N.Less);
- Destroy_Nodes(N.More);
- Free_Node(N);
- end if;
- end Destroy_Nodes;
-
- begin
- if T /= Null then
- Destroy_Nodes(T.Root);
- Free_Tree(T);
- end if;
-
- end Destroy_Deep;
-
- ----------------------------------------------------------------------------
-
- Function Balanced_Tree(
- Count: natural
- ) return Tree
-
- is
- new_Tree: Tree := Create;
-
- procedure subtree(Count: natural; N: in out Node_Ptr)
- is
- new_Node: Node_Ptr;
-
- begin
- if Count = 1 then
- new_Node := new Node'(next_Value, Null, Null);
- elsif Count > 1 then
- new_node := new Node;
- subtree(Count/2, new_Node.Less); -- Half are less
- new_Node.Value := next_Value; -- Median value
- subtree(Count - Count/2 - 1, new_Node.More); -- Other half are more
- end if;
- N := new_Node;
- end subtree;
-
- begin
- new_Tree.Count := Count;
- subtree(Count, new_Tree.Root);
- return new_Tree;
-
- end Balanced_Tree;
-
- ----------------------------------------------------------------------------
-
- Function Copy_Tree(
- T: Tree
- ) return Tree
- is
- I: Iterator;
-
- function next_Val return Value_type
- is
- V: Value_Type;
-
- begin
- Next(I, V);
- return copy_Value(V);
- end next_Val;
-
- function copy_Balanced is new Balanced_Tree(next_Val);
-
- begin
- I := Make_Iter(T); -- Will raise Invalid_Tree if necessary
- return copy_Balanced(Size(T));
-
- end Copy_Tree;
-
- ----------------------------------------------------------------------------
-
- Function Is_Empty( --| Check for an empty tree.
- T: Tree
- ) return boolean is
- begin
- return T = Null or else T.Root = Null;
-
- end Is_Empty;
-
- ----------------------------------------------------------------------------
-
- procedure Find_Node(
- V: Value_Type; --| Value to be located
- N: Node_Ptr; --| subtree to be searched
- Match: out Value_Type; --| Matching value found in the tree
- Found: out Boolean --| TRUE iff a match was found
- )
- is
- D: integer;
-
- begin
- if N = null then
- Found := False;
- return;
- end if;
- D := Difference(V, N.Value);
- if D < 0 then
- Find_Node(V, N.Less, Match, Found);
- elsif D > 0 then
- Find_Node(V, N.More, Match, Found);
- else
- Match := N.Value;
- Found := TRUE;
- end if;
- end Find_Node;
-
- Function Find( --| Search a tree for a value.
- V: Value_Type; --| Value to be located
- T: Tree --| Tree to be searched
- ) return Value_Type --| Raises: Not_Found.
- is
- Found: Boolean;
- Match: Value_Type;
-
- begin
- if T = Null then
- raise Invalid_Tree;
- end if;
- Find_Node(V, T.Root, Match, Found);
- if Found then
- return Match;
- else
- raise Not_Found;
- end if;
- end Find;
-
- Procedure Find( --| Search a tree for a value.
- V: Value_Type; --| Value to be located
- T: Tree; --| Tree to be searched
- Found: out Boolean; --| TRUE iff a match was found
- Match: out Value_Type --| Matching value found in the tree
- ) is
- begin
- if T = Null then
- raise Invalid_Tree;
- end if;
- Find_Node(V, T.Root, Match, Found);
- end Find;
-
- ----------------------------------------------------------------------------
-
- function is_Found( --| Check a tree for a value.
- V: Value_Type; --| Value to be located
- T: Tree --| Tree to be searched
- ) return Boolean
- is
- Found: Boolean;
- Match: Value_Type;
-
- begin
- if T = Null then
- raise Invalid_Tree;
- end if;
- Find_Node(V, T.Root, Match, Found);
- return Found;
-
- end is_Found;
-
- ----------------------------------------------------------------------------
-
- function Size( --| Return the count of values in T.
- T: Tree --| a tree
- ) return natural is
-
- begin
- if T = Null then
- Return 0;
- else
- Return T.Count;
- end if;
-
- end Size;
-
- ----------------------------------------------------------------------------
-
- procedure Visit(
- T: Tree;
- Order: Scan_Kind
- ) is
-
- procedure visit_Inorder(N: Node_Ptr) is
- begin
- if N.Less /= null then
- visit_Inorder(N.Less);
- end if;
- Process(N.Value);
- if N.More /= null then
- visit_Inorder(N.More);
- end if;
- end visit_Inorder;
-
- procedure visit_preorder(N: Node_Ptr) is
- begin
- Process(N.Value);
- if N.Less /= null then
- visit_preorder(N.Less);
- end if;
- if N.More /= null then
- visit_preorder(N.More);
- end if;
- end visit_preorder;
-
- procedure visit_postorder(N: Node_Ptr) is
- begin
- if N.Less /= null then
- visit_postorder(N.Less);
- end if;
- if N.More /= null then
- visit_postorder(N.More);
- end if;
- Process(N.Value);
- end visit_postorder;
-
- begin
- if T = Null then
- raise Invalid_Tree;
- else
- case Order is
- when inorder =>
- Visit_Inorder(T.Root);
- when preorder =>
- Visit_preorder(T.Root);
- when postorder =>
- Visit_postorder(T.Root);
- end case;
- end if;
- end Visit;
-
- ----------------------------------------------------------------------------
-
- function subtree_Iter( --| Create an iterator over a subtree
- N: Node_Ptr;
- P: Iterator
- ) return Iterator is
-
- begin
- if N = Null then
- return new Iterator_Record'(State => Done, Parent => P, subtree => N);
- elsif N.Less = Null then
- return new Iterator_Record'(State => Middle, Parent => P, subtree => N);
- else
- return new Iterator_Record'(State => Left, Parent => P, subtree => N);
- end if;
-
- end subtree_Iter;
-
- function Make_Iter( --| Create an iterator over a tree
- T: Tree
- ) return Iterator is
-
- begin
- if T = Null then
- raise Invalid_Tree;
- end if;
- return subtree_Iter(T.Root, Null);
-
- end Make_Iter;
-
- ----------------------------------------------------------------------------
-
- function More( --| Test for exhausted iterator
- I: Iterator --| The iterator to be tested
- ) return boolean is
-
- begin
- if I = Null then
- return False;
- elsif I.Parent = Null then
- return I.State /= Done and I.subtree /= Null;
- elsif I.State = Done then
- return More(I.Parent);
- else
- return True;
- end if;
-
- end More;
-
- ----------------------------------------------------------------------------
-
- procedure pop_Iterator(
- I: in out Iterator
- )
- is
- NI: Iterator;
- begin
- loop
- NI := I;
- I := I.Parent;
- Free_Iterator(NI);
- exit when I = Null;
- exit when I.State /= Done;
- end loop;
- end pop_Iterator;
-
- procedure Next( --| Scan the next value in I
- I: in out Iterator; --| an active iterator
- V: out Value_Type --| Next value scanned
- ) --| Raises: No_More.
- is
- NI: Iterator;
-
- begin
- if I = Null or I.State = Done then
- raise No_More;
- end if;
- case I.State is
- when Left => -- Return the leftmost value
- while I.subtree.Less /= Null loop -- Find leftmost subtree
- I.State := Middle; -- Middle is next at this level
- I := subtree_Iter(I.subtree.Less, I);
- end loop;
- V := I.subtree.Value;
- if I.subtree.More /= Null then -- There will be more...
- I.State := Right; -- ... coming from the right
- else -- Nothing else here
- pop_Iterator(I); -- Pop up to parent iterator
- end if;
- when Middle =>
- V := I.subtree.Value;
- if I.subtree.More /= Null then -- There will be more...
- I.State := Right; -- ... coming from the right
- else -- Nothing else here so...
- pop_Iterator(I); -- ... Pop up to parent iterator
- end if;
- when Right => -- Return the value on the right
- I.State := Done; -- No more at this level
- I := subtree_Iter(I.subtree.More, I);
- Next(I, V);
- when Done =>
- pop_Iterator(I);
- Next(I, V);
- end case;
-
- end Next;
-
- ----------------------------------------------------------------------------
-
-
- end binary_trees_pkg;
- --::::::::::
- --bit.bdy
- --::::::::::
- package body BIT_FUNCTIONS is
- --
- -- Implementation notes:
- -- this package uses integer arithmetic (mult by 2 and divide by 2)
- -- to accomplish most of the work involved.
- --
- -- The ideal implementation would be similar to the following:
- --
- -- OBJECT : INTEGER;
- -- type BIT_WORD is array (1..16) of BOOLEAN;
- -- pragma PACK (BIT_WORD)
- -- BIT_OBJECT : BIT_WORD;
- -- for BIT_OBJECT use at OBJECT'ADDRESS;
- --
- -- This effectively defined BIT_OBJECT as a bit array, physically
- -- located at the same memory location as OBJECT. As a bit array,
- -- slices and boolean operations can be used! Unfortunately,
- -- the DG/Rolm ADE software does not support the address rep spec.
- --
- --
- WORD_SIZE : constant := 16; -- ASSUME 16 BIT WORDS!
-
- function BIT_EXTRACT (ITEM, START_AT, NBITS : INTEGER) return INTEGER is
- TEMP : INTEGER;
- BIT_VALUE : INTEGER;
- RESULT : INTEGER;
- begin
- TEMP := SHIFT_RIGHT (ITEM, START_AT);
- BIT_VALUE := (TEMP mod 2 ** NBITS);
-
- if BIT_VALUE <= INTEGER'LAST then
- RESULT := BIT_VALUE;
- else
- RESULT := BIT_VALUE - INTEGER'LAST;
- end if;
-
- return RESULT;
- end BIT_EXTRACT;
-
- function UBIT_EXTRACT (ITEM, START_AT, NBITS : INTEGER) return INTEGER is
- TEMP : INTEGER;
- begin
- TEMP := SHIFT_RIGHT (ITEM, START_AT);
- return TEMP mod (2 ** NBITS);
- end UBIT_EXTRACT;
-
- function BIT_INSERT (THIS_ITEM, NBITS, INTO_ITEM, START_AT : INTEGER)
- return INTEGER is
- ITEM : INTEGER;
- begin
- ITEM := THIS_ITEM mod (2 ** NBITS); -- restrict value to size
- return BIT_REMOVE (INTO_ITEM, START_AT, NBITS) +
- SHIFT_LEFT (ITEM, START_AT);
- end BIT_INSERT;
-
- function BIT_REMOVE (ITEM, START_AT, NBITS : INTEGER) return INTEGER is
- KEEP : INTEGER := 0;
- TEMP : INTEGER;
- begin
- if START_AT /= 0 then
- KEEP := ITEM mod (2 ** START_AT);
- end if;
-
- TEMP := SHIFT_RIGHT (ITEM, START_AT + NBITS);
- return SHIFT_LEFT (TEMP, START_AT + NBITS) + KEEP;
- end BIT_REMOVE;
-
- function SHIFT_LEFT (ITEM, NBITS : INTEGER) return INTEGER is
- begin
- return ITEM * (2 ** NBITS);
- end SHIFT_LEFT;
-
- function SHIFT_RIGHT (ITEM, NBITS : INTEGER) return INTEGER is
- begin
- return ITEM / (2 ** NBITS);
- end SHIFT_RIGHT;
-
- function BIT_AND (WORD1, WORD2 : INTEGER) return INTEGER is
- SPARE1 : INTEGER := WORD1;
- SPARE2 : INTEGER := WORD2;
- NEW_WORD : INTEGER := 0;
- BIT1, BIT2, NEW_BIT : INTEGER;
-
- begin
- --
- -- the approach here to extract a single bit at a time from each
- -- word, and then decide upon the logical property. The loop
- -- continues until all bits of the word have been considered,
- -- or until the words become zero in the shifting process.
- --
-
- for INDEX in 1 .. WORD_SIZE loop
- exit when SPARE1 = 0 and SPARE2 = 0;
- BIT1 := SPARE1 mod 2; -- get rightmost bit
- BIT2 := SPARE2 mod 2;
-
- if BIT1 = 1 and BIT2 = 1 then
- NEW_BIT := 1; -- decide upon new bit value
- else
- NEW_BIT := 0;
- end if;
-
- NEW_WORD := NEW_WORD + SHIFT_LEFT (NEW_BIT, INDEX - 1);
- SPARE1 := SHIFT_RIGHT (SPARE1, 1);
- SPARE2 := SHIFT_RIGHT (SPARE2, 1);
- end loop;
-
- return NEW_WORD;
- end BIT_AND;
-
- function BIT_OR (WORD1, WORD2 : INTEGER) return INTEGER is
- SPARE1 : INTEGER := WORD1;
- SPARE2 : INTEGER := WORD2;
- NEW_WORD : INTEGER := 0;
- BIT1, BIT2, NEW_BIT : INTEGER;
-
- begin
- -- processing is identical to BIT_AND, except the logical test is changed
- for INDEX in 1 .. WORD_SIZE loop
- exit when SPARE1 = 0 and SPARE2 = 0;
- BIT1 := SPARE1 mod 2;
- BIT2 := SPARE2 mod 2;
-
- if BIT1 = 1 or BIT2 = 1 then
- NEW_BIT := 1;
- else
- NEW_BIT := 0;
- end if;
-
- NEW_WORD := BIT_INSERT (NEW_BIT, 1, NEW_WORD, INDEX - 1);
- SPARE1 := SHIFT_RIGHT (SPARE1, 1);
- SPARE2 := SHIFT_RIGHT (SPARE2, 1);
- end loop;
-
- return NEW_WORD;
- end BIT_OR;
-
- function BIT_MASK (NBITS : INTEGER) return INTEGER is
- RESULT : INTEGER := 0;
- begin
- for INDEX in 1 .. NBITS loop
- RESULT := RESULT * 2 + 1;
- end loop;
-
- return RESULT;
- end BIT_MASK;
-
- end BIT_FUNCTIONS;
- --::::::::::
- --bplustre.bdy
- --::::::::::
- with Unchecked_Deallocation;
-
- package body BP_Tree is
-
- -- *************************************************************************************
- -- ** This software is part of the Clemson University Computer Science Department's **
- -- ** Ada Software Repository, and is copyrighted (C) 1989 by Clemson University. **
- -- ** Permission to copy without fee all or part of this software is granted, **
- -- ** provided that the copies are not made or distributed for direct commercial **
- -- ** advantage, and that this copyright notice is not deleted or modified. To **
- -- ** copy otherwise, or to republish, requires a fee and/or specific permission. **
- -- ** >> All bug reporters receive a free updated copy once the bug's corrected! << **
- -- ** E-mail to: cpscada@citron.cs.clemson.edu or ...!gatech!hubcap!citron!cpscada. **
- -- *************************************************************************************
-
- ----------------------------------------------------------------------------------------------------------------------------
- type Internal_Node (Index_Node : Boolean);
- ----------------------------------------------------------------------------------------------------------------------------
- type Internal_Node_Pointer is access Internal_Node;
- ----------------------------------------------------------------------------------------------------------------------------
- Maximum_Number_Of_Subtrees_Per_Node : constant := 3; -- This can be any odd number >= 3...
- -- Unfortunately, due to limitations of Ada,
- -- this cannot be made into a generic parameter.
- ----------------------------------------------------------------------------------------------------------------------------
- Minimum_Number_Of_Subtrees_Per_Node : constant := (Maximum_Number_Of_Subtrees_Per_Node/ 2) + 1;
- ----------------------------------------------------------------------------------------------------------------------------
- Minimum_Subtree_Number : constant := Minimum_Number_Of_Subtrees_Per_Node - 1;
- ----------------------------------------------------------------------------------------------------------------------------
- Maximum_Subtree_Number : constant := Maximum_Number_Of_Subtrees_Per_Node - 1;
- ----------------------------------------------------------------------------------------------------------------------------
- type Subtrees is range 0..Maximum_Subtree_Number;
- ----------------------------------------------------------------------------------------------------------------------------
- type Array_Of_Subtrees is array (Subtrees) of Internal_Node_Pointer;
- ----------------------------------------------------------------------------------------------------------------------------
- Maximum_Number_Of_Keys_Per_Node : constant := Maximum_Number_Of_Subtrees_Per_Node - 1;
- ----------------------------------------------------------------------------------------------------------------------------
- type Keys is range 1..Maximum_Number_Of_Keys_Per_Node;
- ----------------------------------------------------------------------------------------------------------------------------
- type Key_Pointer is access Key_Type;
- ----------------------------------------------------------------------------------------------------------------------------
- type Array_Of_Keys is array (Keys) of Key_Pointer;
- ----------------------------------------------------------------------------------------------------------------------------
- type Internal_Node (Index_Node : Boolean) is
- record
- case Index_Node is
- when True => Maximum_Subtree_Index : Subtrees;
- Key : Array_Of_Keys;
- Subtree : Array_Of_Subtrees;
-
- when False => Preceding_Leaf : Internal_Node_Pointer := null;
- Following_Leaf : Internal_Node_Pointer := null;
- Key_Value : Key_Pointer;
- Item_Container : Non_Key_Item_Container;
- end case;
- end record;
- ----------------------------------------------------------------------------------------------------------------------------
- type B_Plus_Tree_Descriptor is
- record
- Root_Node : Internal_Node_Pointer;
- Current_Leaf : Internal_Node_Pointer;
- Minimum_Key : Key_Pointer;
- Number_Of_Keys_Stored : Natural;
- end record;
- ----------------------------------------------------------------------------------------------------------------------------
- type Non_Key_Item_Pointer is access Non_Key_Item_Type;
- ----------------------------------------------------------------------------------------------------------------------------
- type Type_Of_Deletion is (Key, Non_Key_Object);
- ----------------------------------------------------------------------------------------------------------------------------
- Null_Node_Pointer : Internal_Node_Pointer := null; -- acceptable as an {in out} parameter...
- Null_Key_Pointer : Key_Pointer := null; -- acceptable as an {in out} parameter...
- ----------------------------------------------------------------------------------------------------------------------------
- function Empty (Targeted_B_Plus_Tree : in B_Plus_Tree) return Boolean is
-
- begin -- function Empty
- return (Targeted_B_Plus_Tree = null);
- end Empty;
- ----------------------------------------------------------------------------------------------------------------------------
- function Number_Of_Keys_Stored (Targeted_B_Plus_Tree : in B_Plus_Tree) return Natural is
-
- begin -- function Number_Of_Keys_Stored
- if (Targeted_B_Plus_Tree = null) then
- return 0;
- else
- return Targeted_B_Plus_Tree.Number_Of_Keys_Stored;
- end if;
- end Number_Of_Keys_Stored;
- ----------------------------------------------------------------------------------------------------------------------------
- procedure Exchange (First_Key_Pointer : in out Key_Pointer;
- Second_Key_Pointer : in out Key_Pointer) is
-
- Temp_Key_Pointer : Key_Pointer := First_Key_Pointer;
-
- begin -- procedure Exchange
- First_Key_Pointer := Second_Key_Pointer;
- Second_Key_Pointer := Temp_Key_Pointer;
- end Exchange;
- ----------------------------------------------------------------------------------------------------------------------------
- procedure Exchange (First_Internal_Node_Pointer : in out Internal_Node_Pointer;
- Second_Internal_Node_Pointer : in out Internal_Node_Pointer) is
-
- Temp_Internal_Node_Pointer : Internal_Node_Pointer := First_Internal_Node_Pointer;
-
- begin -- procedure Exchange
- First_Internal_Node_Pointer := Second_Internal_Node_Pointer;
- Second_Internal_Node_Pointer := Temp_Internal_Node_Pointer;
- end Exchange;
- ----------------------------------------------------------------------------------------------------------------------------
- procedure Exchange (First_B_Plus_Tree : in out B_Plus_Tree;
- Second_B_Plus_Tree : in out B_Plus_Tree) is
-
- Temporary_B_Plus_Tree : B_Plus_Tree := First_B_Plus_Tree;
-
- begin -- procedure Exchange
- First_B_Plus_Tree := Second_B_Plus_Tree;
- Second_B_Plus_Tree := Temporary_B_Plus_Tree;
- end Exchange;
- ----------------------------------------------------------------------------------------------------------------------------
- function Determine_Path_Of_Descent (Targeted_Index_Node : in Internal_Node_Pointer;
- Key_Value : in Key_Type ) return Subtrees is
-
- Path_Number : Subtrees := 0;
-
- begin -- function Determine_Path_Of_Descent
- while (Path_Number < Maximum_Subtree_Number)
- and then ( Targeted_Index_Node.Key (Keys'Val (Subtrees'Pos (Path_Number) +1) ) /= null )
- and then not Less_Than (Key_Value, Targeted_Index_Node.Key (Keys'Val (Subtrees'Pos(Path_Number)+1)).all) loop
- Path_Number := Path_Number + 1;
- end loop;
- return Path_Number;
- end Determine_Path_Of_Descent;
- ----------------------------------------------------------------------------------------------------------------------------
- procedure Left_Shift (Node_Being_Shifted : in out Internal_Node_Pointer;
- Minimum_Key_In_Subtree : in out Key_Pointer;
- Leftmost_Shift_Point : in Subtrees;
- Rightmost_Shift_Point : in Subtrees ) is
-
- -- Assumption: Leftmost_Shift_Point > 0...
-
- begin -- procedure Left_Shift
- for Subtree_Number in Leftmost_Shift_Point..Rightmost_Shift_Point loop
- Node_Being_Shifted.Subtree (Subtree_Number - 1) := Node_Being_Shifted.Subtree (Subtree_Number);
- if (Subtree_Number > 1) then
- Node_Being_Shifted.Key ( Keys'Val (Subtrees'Pos (Subtree_Number - 1) ) )
- := Node_Being_Shifted.Key ( Keys'Val (Subtrees'Pos (Subtree_Number) ) );
- else
- Minimum_Key_In_Subtree := Node_Being_Shifted.Key ( Keys'Val (Subtrees'Pos (Subtree_Number) ) );
- end if;
- end loop;
- end Left_Shift;
- ----------------------------------------------------------------------------------------------------------------------------
- procedure Right_Shift (Node_Being_Shifted : in out Internal_Node_Pointer;
- Minimum_Key_In_Subtree : in out Key_Pointer;
- Leftmost_Shift_Point : in Subtrees;
- Rightmost_Shift_Point : in Subtrees ) is
-
- -- Assumption: Rightmost_Shift_Point < Maximum_Subtree_Number...
-
- begin -- procedure Right_Shift
- for Subtree_Number in reverse Leftmost_Shift_Point..Rightmost_Shift_Point loop
- Node_Being_Shifted.Subtree (Subtree_Number + 1) := Node_Being_Shifted.Subtree (Subtree_Number);
- if (Subtree_Number > 0) then
- Node_Being_Shifted.Key ( Keys'Val (Subtrees'Pos (Subtree_Number + 1) ) )
- := Node_Being_Shifted.Key ( Keys'Val (Subtrees'Pos (Subtree_Number) ) );
- else
- Node_Being_Shifted.Key (1) := Minimum_Key_In_Subtree;
- end if;
- end loop;
- end Right_Shift;
- ----------------------------------------------------------------------------------------------------------------------------
- procedure Insert_Extra_Subtree (Targeted_Index_Node : in out Internal_Node_Pointer;
- Minimum_Key_In_Subtree : in out Key_Pointer;
- Extra_Subtree : in out Internal_Node_Pointer;
- Minimum_Key_In_Extra_Subtree : in out Key_Pointer ) is
-
- -- Assumption: Targeted_Index_Node.Maximum_Subtree_Index < Maximum_Subtree_Number...
-
- Path_Of_Descent : Subtrees;
- Insertion_Point : Subtrees;
-
- begin -- procedure Insert_Extra_Subtree
- Path_Of_Descent := Determine_Path_Of_Descent (Targeted_Index_Node, Minimum_Key_In_Extra_Subtree.all);
- if (Path_Of_Descent > 0)
- or else Less_Than (Minimum_Key_In_Subtree.all, Minimum_Key_In_Extra_Subtree.all) then
- Insertion_Point := Path_Of_Descent + 1;
- else
- Insertion_Point := Path_Of_Descent;
- end if;
- Right_Shift (Targeted_Index_Node, Minimum_Key_In_Subtree, Insertion_Point, Targeted_Index_Node.Maximum_Subtree_Index);
- Targeted_Index_Node.Subtree (Insertion_Point) := Extra_Subtree;
- if (Insertion_Point = 0) then
- Minimum_Key_In_Subtree := Minimum_Key_In_Extra_Subtree;
- else
- Targeted_Index_Node.Key ( Keys'Val (Subtrees'Pos (Insertion_Point))) := Minimum_Key_In_Extra_Subtree;
- end if;
- Targeted_Index_Node.Maximum_Subtree_Index := Targeted_Index_Node.Maximum_Subtree_Index + 1;
- Extra_Subtree := null;
- Minimum_Key_In_Extra_Subtree := null;
- end Insert_Extra_Subtree;
- ----------------------------------------------------------------------------------------------------------------------------
- procedure Delete_Subtree (Targeted_Node : in out Internal_Node_Pointer;
- Minimum_Key_In_Subtree : in out Key_Pointer;
- Targeted_Subtree : in Subtrees ) is
-
- begin -- procedure Delete_Subtree
- if (Targeted_Subtree < Targeted_Node.Maximum_Subtree_Index) then
- Left_Shift (Targeted_Node, Minimum_Key_In_Subtree, (Targeted_Subtree+1), Targeted_Node.Maximum_Subtree_Index);
- end if;
- Targeted_Node.Subtree (Targeted_Node.Maximum_Subtree_Index) := null;
- if (Targeted_Node.Maximum_Subtree_Index = 0) then
- Minimum_Key_In_Subtree := null;
- else
- Targeted_Node.Key ( Keys'Val ( Subtrees'Pos (Targeted_Node.Maximum_Subtree_Index) ) ) := null;
- Targeted_Node.Maximum_Subtree_Index := Targeted_Node.Maximum_Subtree_Index - 1;
- end if;
- end Delete_Subtree;
- ----------------------------------------------------------------------------------------------------------------------------
- procedure Insert_Item (Targeted_B_Plus_Tree : in out B_Plus_Tree;
- Key_Value : in Key_Type;
- Non_Key_Information : in Non_Key_Item_Type) is
-
-
- New_Root : Internal_Node_Pointer;
- Extra_Subtree : Internal_Node_Pointer := null;
- Minimum_Key_In_Extra_Subtree : Key_Pointer := null;
-
- procedure Generate_New_Leaf (Pointer_To_Preceding_Leaf : in Internal_Node_Pointer;
- Pointer_To_New_Leaf : in out Internal_Node_Pointer;
- Pointer_To_Following_Leaf : in Internal_Node_Pointer;
- Value_Of_New_Key : in Key_Type ) is
-
- begin -- procedure Generate_New_Leaf
- Pointer_To_New_Leaf := new Internal_Node (Index_Node => False);
- Pointer_To_New_Leaf.Preceding_Leaf := Pointer_To_Preceding_Leaf;
- Pointer_To_New_Leaf.Following_Leaf := Pointer_To_Following_Leaf;
- if (Pointer_To_Preceding_Leaf /= null) then
- Pointer_To_Preceding_Leaf.Following_Leaf := Pointer_To_New_Leaf;
- end if;
- if (Pointer_To_Following_Leaf /= null) then
- Pointer_To_Following_Leaf.Preceding_Leaf := Pointer_To_New_Leaf;
- end if;
- Pointer_To_New_Leaf.Key_Value := new Key_Type;
- Assign (Pointer_To_New_Leaf.Key_Value.all, Value_Of_New_Key);
- end Generate_New_Leaf;
-
-
- procedure Create_New_B_Plus_Tree (Targeted_B_Plus_Tree : in out B_Plus_Tree;
- Key_Value : in Key_Type;
- Non_Key_Information : in Non_Key_Item_Type) is
-
- begin -- procedure Create_New_B_Plus_Tree
- Targeted_B_Plus_Tree := new B_Plus_Tree_Descriptor;
- Targeted_B_Plus_Tree.Root_Node := new Internal_Node (Index_Node => True);
- Generate_New_Leaf (null, Targeted_B_Plus_Tree.Root_Node.Subtree(0), null, Key_Value);
- Insert (Targeted_B_Plus_Tree.Root_Node.Subtree(0).Item_Container, Non_Key_Information);
- Targeted_B_Plus_Tree.Current_Leaf := Targeted_B_Plus_Tree.Root_Node.Subtree(0);
- Targeted_B_Plus_Tree.Minimum_Key := Targeted_B_Plus_Tree.Root_Node.Subtree(0).Key_Value;
- Targeted_B_Plus_Tree.Root_Node.Maximum_Subtree_Index := 0;
- Targeted_B_Plus_Tree.Number_Of_Keys_Stored := 1;
- end Create_New_B_Plus_Tree;
-
-
- procedure Insert_Subtree (Left_Sibling : in out Internal_Node_Pointer;
- Minimum_Key_In_Left_Sibling : in out Key_Pointer;
- Targeted_Index_Node : in out Internal_Node_Pointer;
- Minimum_Key_In_Subtree : in out Key_Pointer;
- Right_Sibling : in out Internal_Node_Pointer;
- Minimum_Key_In_Right_Sibling : in out Key_Pointer;
- Extra_Subtree : in out Internal_Node_Pointer;
- Minimum_Key_In_Extra_Subtree : in out Key_Pointer ) is
-
-
- Room_In_Left_Sibling : Boolean := ( (Left_Sibling /= null)
- and then (Left_Sibling.Index_Node = True)
- and then (Left_Sibling.Maximum_Subtree_Index < Maximum_Subtree_Number) );
-
- Room_In_Right_Sibling : Boolean := ( (Right_Sibling /= null)
- and then (Right_Sibling.Index_Node = True)
- and then (Right_Sibling.Maximum_Subtree_Index < Maximum_Subtree_Number) );
-
- type Overflow_Preference is (Return_Leftmost_Subtree, Return_Rightmost_Subtree);
-
-
- procedure Insert_And_Overflow (Targeted_Index_Node : in out Internal_Node_Pointer;
- Minimum_Key_In_Subtree : in out Key_Pointer;
- Extra_Subtree : in out Internal_Node_Pointer;
- Minimum_Key_In_Extra_Subtree : in out Key_Pointer;
- Overflow_Directions : in Overflow_Preference ) is
-
- Temp_Subtree : Internal_Node_Pointer;
- Temp_Key : Key_Pointer;
- Insertion_Point : Subtrees := Determine_Path_Of_Descent (Targeted_Index_Node, Minimum_Key_In_Extra_Subtree.all);
-
- begin -- procedure Insert_And_Overflow
- if (Overflow_Directions = Return_Leftmost_Subtree) then
- if (Insertion_Point = 0) then
- if Less_Than (Minimum_Key_In_Subtree.all, Minimum_Key_In_Extra_Subtree.all) then
- Exchange (Targeted_Index_Node.Subtree(0), Extra_Subtree);
- Exchange (Minimum_Key_In_Extra_Subtree, Minimum_Key_In_Subtree);
- end if;
- else
- Temp_Subtree := Targeted_Index_Node.Subtree(0);
- Temp_Key := Minimum_Key_In_Subtree;
- Left_Shift (Targeted_Index_Node, Minimum_Key_In_Subtree, 1, Insertion_Point);
- Targeted_Index_Node.Subtree (Insertion_Point) := Extra_Subtree;
- Targeted_Index_Node.Key (Keys'Val(Subtrees'Pos(Insertion_Point))) := Minimum_Key_In_Extra_Subtree;
- Extra_Subtree := Temp_Subtree;
- Minimum_Key_In_Extra_Subtree := Temp_Key;
- end if;
- elsif (Overflow_Directions = Return_Rightmost_Subtree) then
- if (Insertion_Point + 1 >= Maximum_Subtree_Number) then
- if not Less_Than (Targeted_Index_Node.Key (Maximum_Subtree_Number).all, Minimum_Key_In_Extra_Subtree.all) then
- Exchange (Extra_Subtree, Targeted_Index_Node.Subtree (Maximum_Subtree_Number) );
- Exchange (Minimum_Key_In_Extra_Subtree,
- Targeted_Index_Node.Key (Keys'Val (Subtrees'Pos (Maximum_Subtree_Number) ) ) );
- end if;
- else
- if not (Insertion_Point = 0)
- or else Less_Than (Minimum_Key_In_Subtree.all, Minimum_Key_In_Extra_Subtree.all) then
- Insertion_Point := Insertion_Point + 1;
- end if;
- Temp_Subtree := Targeted_Index_Node.Subtree (Maximum_Subtree_Number);
- Temp_Key := Targeted_Index_Node.Key (Maximum_Subtree_Number);
- Right_Shift (Targeted_Index_Node, Minimum_Key_In_Subtree, Insertion_Point, (Maximum_Subtree_Number - 1));
- Targeted_Index_Node.Subtree (Insertion_Point) := Extra_Subtree;
- if (Insertion_Point = 0) then
- Minimum_Key_In_Subtree := Minimum_Key_In_Extra_Subtree;
- else
- Targeted_Index_Node.Key ( Keys'Val ( Subtrees'Pos ( Insertion_Point ) ) ) := Minimum_Key_In_Extra_Subtree;
- end if;
- Extra_Subtree := Temp_Subtree;
- Minimum_Key_In_Extra_Subtree := Temp_Key;
- end if;
- end if;
- end Insert_And_Overflow;
-
-
- procedure Insert_And_Partition (Targeted_Index_Node : in out Internal_Node_Pointer;
- Minimum_Key_In_Subtree : in out Key_Pointer;
- Extra_Subtree : in out Internal_Node_Pointer;
- Minimum_Key_In_Extra_Subtree : in out Key_Pointer ) is
-
- Insertion_Point : Subtrees;
- New_Extra_Subtree : Internal_Node_Pointer;
- Minimum_Key_In_New_Extra_Subtree : Key_Pointer;
-
- procedure Partition (Targeted_Index_Node : in out Internal_Node_Pointer;
- Minimum_Key_In_Subtree : in out Key_Pointer;
- Node_Split_Point : in Subtrees;
- New_Extra_Subtree : in out Internal_Node_Pointer;
- Minimum_Key_In_New_Extra_Subtree : in out Key_Pointer ) is
-
- begin -- procedure Partition
-
- New_Extra_Subtree := new Internal_Node (Index_Node => True);
-
- for Transferred_Subtree_Index in reverse Node_Split_Point..Maximum_Subtree_Number loop
- New_Extra_Subtree.Subtree (Transferred_Subtree_Index - Node_Split_Point)
- := Targeted_Index_Node.Subtree (Transferred_Subtree_Index);
- Targeted_Index_Node.Subtree (Transferred_Subtree_Index) := null;
- if (Transferred_Subtree_Index - Node_Split_Point) > 0 then
- New_Extra_Subtree.Key (Keys'Val ( Subtrees'Pos (Transferred_Subtree_Index - Node_Split_Point)))
- := Targeted_Index_Node.Key (Keys'Val ( Subtrees'Pos (Transferred_Subtree_Index)));
- else
- Minimum_Key_In_New_Extra_Subtree
- := Targeted_Index_Node.Key (Keys'Val (Subtrees'Pos (Transferred_Subtree_Index) ) );
- end if;
- Targeted_Index_Node.Key (Keys'Val (Subtrees'Pos (Transferred_Subtree_Index))) := null;
- end loop;
-
- Targeted_Index_Node.Maximum_Subtree_Index := Node_Split_Point - 1;
-
- New_Extra_Subtree.Maximum_Subtree_Index := Maximum_Subtree_Number - Node_Split_Point;
-
- end Partition;
-
- begin -- procedure Insert_And_Partition
-
- Insertion_Point := Determine_Path_Of_Descent (Targeted_Index_Node, Minimum_Key_In_Extra_Subtree.all);
-
- if (Insertion_Point < Minimum_Subtree_Number) then
- Partition (Targeted_Index_Node, Minimum_Key_In_Subtree, Minimum_Subtree_Number,
- New_Extra_Subtree, Minimum_Key_In_New_Extra_Subtree);
- Insert_Extra_Subtree (Targeted_Index_Node, Minimum_Key_In_Subtree, Extra_Subtree, Minimum_Key_In_Extra_Subtree);
- else
- Partition (Targeted_Index_Node, Minimum_Key_In_Subtree, Minimum_Subtree_Number + 1,
- New_Extra_Subtree, Minimum_Key_In_New_Extra_Subtree);
- Insert_Extra_Subtree (New_Extra_Subtree, Minimum_Key_In_New_Extra_Subtree,
- Extra_Subtree, Minimum_Key_In_Extra_Subtree);
- end if;
-
- Extra_Subtree := New_Extra_Subtree;
- Minimum_Key_In_Extra_Subtree := Minimum_Key_In_New_Extra_Subtree;
-
- end Insert_And_Partition;
-
-
- begin -- procedure Insert_Subtree
- if (Targeted_Index_Node.Maximum_Subtree_Index < Maximum_Subtree_Number) then
- Insert_Extra_Subtree (Targeted_Index_Node, Minimum_Key_In_Subtree, Extra_Subtree, Minimum_Key_In_Extra_Subtree);
- elsif Room_In_Left_Sibling and not Room_In_Right_Sibling then
- Insert_And_Overflow (Targeted_Index_Node, Minimum_Key_In_Subtree,
- Extra_Subtree, Minimum_Key_In_Extra_Subtree, Return_Leftmost_Subtree);
- Insert_Extra_Subtree (Left_Sibling, Minimum_Key_In_Left_Sibling, Extra_Subtree, Minimum_Key_In_Extra_Subtree);
- elsif Room_In_Right_Sibling then
- Insert_And_Overflow (Targeted_Index_Node, Minimum_Key_In_Subtree,
- Extra_Subtree, Minimum_Key_In_Extra_Subtree, Return_Rightmost_Subtree);
- Insert_Extra_Subtree (Right_Sibling, Minimum_Key_In_Right_Sibling, Extra_Subtree, Minimum_Key_In_Extra_Subtree);
- else
- Insert_And_Partition (Targeted_Index_Node, Minimum_Key_In_Subtree, Extra_Subtree, Minimum_Key_In_Extra_Subtree);
- end if;
- end Insert_Subtree;
-
-
- procedure Descend_And_Insert_Leaf (Left_Sibling : in Internal_Node_Pointer;
- Target_Node : in Internal_Node_Pointer;
- Right_Sibling : in Internal_Node_Pointer;
- Minimum_Key_In_Subtree : in out Key_Pointer;
- Extra_Subtree : in out Internal_Node_Pointer;
- Minimum_Key_In_Extra_Subtree : in out Key_Pointer ) is
-
- Path_Of_Descent : Subtrees;
-
- begin -- procedure Descend_And_Insert_Leaf
-
- if (Target_Node.Index_Node = False) then
-
- if Equal (Target_Node.Key_Value.all, Key_Value) then
-
- Insert (Target_Node.Item_Container, Non_Key_Information);
- Targeted_B_Plus_Tree.Current_Leaf := Target_Node;
-
- else
-
- if Less_Than (Key_Value, Target_Node.Key_Value.all) then
- Generate_New_Leaf (Target_Node.Preceding_Leaf, Extra_Subtree, Target_Node, Key_Value);
- else
- Generate_New_Leaf (Target_Node, Extra_Subtree, Target_Node.Following_Leaf, Key_Value);
- end if;
-
- Insert (Extra_Subtree.Item_Container, Non_Key_Information);
- Minimum_Key_In_Extra_Subtree := Extra_Subtree.Key_Value;
- Targeted_B_Plus_Tree.Current_Leaf := Extra_Subtree;
-
- Targeted_B_Plus_Tree.Number_Of_Keys_Stored := Targeted_B_Plus_Tree.Number_Of_Keys_Stored + 1;
-
- end if;
-
- else
-
- Path_Of_Descent := Determine_Path_Of_Descent (Target_Node, Key_Value);
-
- case Path_Of_Descent is
-
- when 0
- => Descend_And_Insert_Leaf (Null_Node_Pointer,
- Target_Node.Subtree (0),
- Target_Node.Subtree (1),
- Minimum_Key_In_Subtree,
- Extra_Subtree, Minimum_Key_In_Extra_Subtree);
- if (Extra_Subtree /= null)
- and (Target_Node.Subtree (Path_Of_Descent).all.Index_Node = True) then
- Insert_Subtree (Null_Node_Pointer,
- Null_Key_Pointer,
- Target_Node.Subtree (0),
- Minimum_Key_In_Subtree,
- Target_Node.Subtree (1),
- Target_Node.Key (1),
- Extra_Subtree, Minimum_Key_In_Extra_Subtree);
- end if;
-
- when 1..(Maximum_Subtree_Number - 1)
- => Descend_And_Insert_Leaf (Target_Node.Subtree (Path_Of_Descent - 1),
- Target_Node.Subtree (Path_Of_Descent),
- Target_Node.Subtree (Path_Of_Descent + 1),
- Target_Node.Key ( Keys'Val ( Subtrees'Pos (Path_Of_Descent))),
- Extra_Subtree, Minimum_Key_In_Extra_Subtree);
- if (Extra_Subtree /= null)
- and (Target_Node.Subtree (Path_Of_Descent).Index_Node = True) then
- if (Path_Of_Descent = 1) then
- Insert_Subtree (Target_Node.Subtree (0),
- Minimum_Key_In_Subtree,
- Target_Node.Subtree (1),
- Target_Node.Key (1),
- Target_Node.Subtree (2),
- Target_Node.Key (2),
- Extra_Subtree, Minimum_Key_In_Extra_Subtree);
- else
- Insert_Subtree (Target_Node.Subtree (Path_Of_Descent - 1),
- Target_Node.Key (Keys'Val (Subtrees'Pos (Path_Of_Descent - 1))),
- Target_Node.Subtree (Path_Of_Descent),
- Target_Node.Key ( Keys'Val ( Subtrees'Pos (Path_Of_Descent))),
- Target_Node.Subtree (Path_Of_Descent + 1),
- Target_Node.Key ( Keys'Val (Subtrees'Pos (Path_Of_Descent-1))),
- Extra_Subtree, Minimum_Key_In_Extra_Subtree);
- end if;
- end if;
-
- when Maximum_Subtree_Number
- => Descend_And_Insert_Leaf (Target_Node.Subtree (Maximum_Subtree_Number - 1),
- Target_Node.Subtree (Maximum_Subtree_Number),
- Null_Node_Pointer,
- Target_Node.Key (Maximum_Subtree_Number),
- Extra_Subtree, Minimum_Key_In_Extra_Subtree);
- if (Extra_Subtree /= null)
- and (Target_Node.Subtree (Path_Of_Descent).Index_Node = True) then
- Insert_Subtree (Target_Node.Subtree (Maximum_Subtree_Number - 1),
- Target_Node.Key (Maximum_Subtree_Number - 1),
- Target_Node.Subtree (Maximum_Subtree_Number),
- Target_Node.Key (Maximum_Subtree_Number),
- Null_Node_Pointer,
- Null_Key_Pointer,
- Extra_Subtree, Minimum_Key_In_Extra_Subtree);
- end if;
-
- end case;
-
- end if;
-
- end Descend_And_Insert_Leaf;
-
-
- begin -- procedure Insert_Item
-
- if (Targeted_B_Plus_Tree = null) then
-
- Create_New_B_Plus_Tree (Targeted_B_Plus_Tree, Key_Value, Non_Key_Information);
-
- else
-
- Descend_And_Insert_Leaf (null, Targeted_B_Plus_Tree.Root_Node, null,
- Targeted_B_Plus_Tree.Minimum_Key, Extra_Subtree, Minimum_Key_In_Extra_Subtree);
-
- if (Extra_Subtree /= null) then
- Insert_Subtree (Null_Node_Pointer, Null_Key_Pointer,
- Targeted_B_Plus_Tree.Root_Node, Targeted_B_Plus_Tree.Minimum_Key,
- Null_Node_Pointer, Null_Key_Pointer,
- Extra_Subtree, Minimum_Key_In_Extra_Subtree);
- end if;
-
- if (Extra_Subtree /= null) then
- New_Root := new Internal_Node (Index_Node => True);
- New_Root.Subtree(0) := Targeted_B_Plus_Tree.Root_Node;
- New_Root.Subtree(1) := Extra_Subtree;
- New_Root.Key(1) := Minimum_Key_In_Extra_Subtree;
- New_Root.Maximum_Subtree_Index := 1;
- Targeted_B_Plus_Tree.Root_Node := New_Root;
- end if;
-
- end if;
-
- end Insert_Item;
- ----------------------------------------------------------------------------------------------------------------------------
- procedure Destroy is new Unchecked_Deallocation (Key_Type, Key_Pointer);
- ----------------------------------------------------------------------------------------------------------------------------
- procedure Destroy is new Unchecked_Deallocation (Internal_Node, Internal_Node_Pointer);
- ----------------------------------------------------------------------------------------------------------------------------
- procedure Annihilate is new Unchecked_Deallocation (B_Plus_Tree_Descriptor, B_Plus_Tree);
- ----------------------------------------------------------------------------------------------------------------------------
- procedure Destroy_Subtree (Target_Node : in out Internal_Node_Pointer) is
-
- begin -- procedure Destroy_Subtree
- if (Target_Node /= null) then
- if (Target_Node.Index_Node = False) then
- if (Target_Node.Preceding_Leaf /= null) then
- Target_Node.Preceding_Leaf.Following_Leaf := Target_Node.Following_Leaf;
- end if;
- if (Target_Node.Following_Leaf /= null) then
- Target_Node.Following_Leaf.Preceding_Leaf := Target_Node.Preceding_Leaf;
- end if;
- Destroy (Target_Node.Key_Value);
- Destroy_Contents (Target_Node.Item_Container);
- Destroy (Target_Node);
- else
- for Subtree_Number in Subtrees loop
- Destroy_Subtree (Target_Node.Subtree (Subtree_Number));
- end loop;
- Destroy (Target_Node);
- end if;
- end if;
- end Destroy_Subtree;
- ----------------------------------------------------------------------------------------------------------------------------
- procedure Destroy (Targeted_B_Plus_Tree : in out B_Plus_Tree) is
-
- -- Destroys all keys and all associated containers, and renders the tree Empty.
-
- begin -- procedure Destroy
- if not Empty (Targeted_B_Plus_Tree) then
- Destroy_Subtree (Targeted_B_Plus_Tree.Root_Node);
- Annihilate (Targeted_B_Plus_Tree);
- end if;
- end Destroy;
- ----------------------------------------------------------------------------------------------------------------------------
- procedure Destroy (Targeted_Object : in out Pointer_To_B_Plus_Tree) is
-
- procedure Annihilate is new Unchecked_Deallocation (B_Plus_Tree, Pointer_To_B_Plus_Tree);
-
- begin -- procedure Destroy
- if (Targeted_Object /= null) then
- Destroy (Targeted_Object.all);
- Annihilate (Targeted_Object);
- end if;
- end Destroy;
- ----------------------------------------------------------------------------------------------------------------------------
- procedure Descend_And_Delete (Targeted_B_Plus_Tree : in out B_Plus_Tree;
- Target_Node : in out Internal_Node_Pointer;
- Minimum_Key_In_Subtree : in out Key_Pointer;
- Deletion_Type : in Type_Of_Deletion;
- Target_Key : in Key_Type;
- Target_Non_Key_Object : in Non_Key_Item_Type) is
-
-
- Path_Of_Descent : Subtrees;
-
-
- procedure Delete_From_Leaf (Target_Leaf : in out Internal_Node_Pointer;
- Deletion_Type : in Type_Of_Deletion;
- Target_Key : in Key_Type;
- Target_Non_Key_Object : in Non_Key_Item_Type) is
-
- procedure Delete_Leaf (Targeted_B_Plus_Tree : in out B_Plus_Tree;
- Target_Leaf : in out Internal_Node_Pointer) is
-
- begin -- procedure Delete_Leaf
- if (Targeted_B_Plus_Tree.Current_Leaf = Target_Leaf) then
- Targeted_B_Plus_Tree.Current_Leaf := null;
- end if;
- if (Targeted_B_Plus_Tree.Minimum_Key = Target_Leaf.Key_Value) then
- if (Target_Leaf.Following_Leaf /= null) then
- Targeted_B_Plus_Tree.Minimum_Key := Target_Leaf.Following_Leaf.Key_Value;
- else
- Targeted_B_Plus_Tree.Minimum_Key := null;
- end if;
- end if;
- Destroy_Subtree (Target_Leaf);
- Targeted_B_Plus_Tree.Number_Of_Keys_Stored := Targeted_B_Plus_Tree.Number_Of_Keys_Stored - 1;
- end Delete_Leaf;
-
- begin -- procedure Delete_From_Leaf
- if not Equal (Target_Leaf.Key_Value.all, Target_Key) then
- raise Key_Does_Not_Exist_In_This_B_Plus_Tree;
- elsif (Deletion_Type = Non_Key_Object) then
- Delete (Target_Leaf.Item_Container, Target_Non_Key_Object);
- if Empty (Target_Leaf.Item_Container) then
- Delete_Leaf (Targeted_B_Plus_Tree, Target_Leaf);
- end if;
- else -- (Deletion_Type = Key)
- Delete_Leaf (Targeted_B_Plus_Tree, Target_Leaf);
- end if;
- end Delete_From_Leaf;
-
-
- procedure Redistribute_Subtrees (Target_Node : in out Internal_Node_Pointer;
- Minimum_Key_In_Subtree : in out Key_Pointer;
- Path_Of_Descent : in Subtrees ) is
-
- Needy_Node : Internal_Node_Pointer;
- Minimum_Key_In_Needy_Node : Key_Pointer;
- Left_Sibling : Internal_Node_Pointer := null;
- Minimum_Key_In_Left_Sibling : Key_Pointer := null;
- Right_Sibling : Internal_Node_Pointer := null;
- Minimum_Key_In_Right_Sibling : Key_Pointer := null;
- Extras_In_Left_Sibling : Boolean;
- Extras_In_Right_Sibling : Boolean;
-
- begin -- procedure Redistribute_Subtrees
-
- Needy_Node := Target_Node.Subtree (Path_Of_Descent);
-
- if (Path_Of_Descent = 0) then
- Minimum_Key_In_Needy_Node := Minimum_Key_In_Subtree;
- else
- Minimum_Key_In_Needy_Node := Target_Node.Key ( Keys'Val ( Subtrees'Pos (Path_Of_Descent) ) );
- end if;
-
- case Path_Of_Descent is
-
- when 0 => Right_Sibling := Target_Node.Subtree (1);
- Minimum_Key_In_Right_Sibling := Target_Node.Key (1);
-
- when 1 => Left_Sibling := Target_Node.Subtree (0);
- Minimum_Key_In_Left_Sibling := Minimum_Key_In_Subtree;
- Right_Sibling := Target_Node.Subtree (2);
- Minimum_Key_In_Right_Sibling := Target_Node.Key (2);
-
- when 2..(Maximum_Subtree_Number - 1)
- => Left_Sibling := Target_Node.Subtree (Path_Of_Descent - 1);
- Minimum_Key_In_Left_Sibling := Target_Node.Key (Keys'Val(Subtrees'Pos(Path_Of_Descent - 1)));
- Right_Sibling := Target_Node.Subtree (Path_Of_Descent + 1);
- Minimum_Key_In_Right_Sibling := Target_Node.Key (Keys'Val(Subtrees'Pos(Path_Of_Descent + 1)));
-
- when Maximum_Subtree_Number
- => Left_Sibling := Target_Node.Subtree (Maximum_Subtree_Number - 1);
- Minimum_Key_In_Left_Sibling := Target_Node.Key (Maximum_Subtree_Number - 1);
-
- end case;
-
- Extras_In_Left_Sibling := ( (Left_Sibling /= null)
- and then (Left_Sibling.Index_Node = True)
- and then (Left_Sibling.Maximum_Subtree_Index > Minimum_Subtree_Number));
-
- Extras_In_Right_Sibling := ( (Right_Sibling /= null)
- and then (Right_Sibling.Index_Node = True)
- and then (Right_Sibling.Maximum_Subtree_Index > Minimum_Subtree_Number));
-
- if Extras_In_Left_Sibling and not Extras_In_Right_Sibling then
-
- Insert_Extra_Subtree (Needy_Node, Minimum_Key_In_Needy_Node,
- Left_Sibling.Subtree (Left_Sibling.Maximum_Subtree_Index),
- Left_Sibling.Key (Keys'Val(Subtrees'Pos(Left_Sibling.Maximum_Subtree_Index))));
- Delete_Subtree (Left_Sibling, Minimum_Key_In_Left_Sibling, Left_Sibling.Maximum_Subtree_Index);
- Target_Node.Key ( Keys'Val ( Subtrees'Pos (Path_Of_Descent) ) ) := Minimum_Key_In_Needy_Node;
-
- elsif Extras_In_Right_Sibling then
-
- Insert_Extra_Subtree (Needy_Node, Minimum_Key_In_Needy_Node, Right_Sibling.Subtree(0), Minimum_Key_In_Right_Sibling);
- Delete_Subtree (Right_Sibling, Minimum_Key_In_Right_Sibling, 0);
- Target_Node.Key ( Keys'Val ( Subtrees'Pos (Path_Of_Descent + 1) ) ) := Minimum_Key_In_Right_Sibling;
-
- elsif (Right_Sibling = null) or else (Left_Sibling /= null) then
-
- Insert_Extra_Subtree (Left_Sibling, Minimum_Key_In_Left_Sibling, Needy_Node.Subtree (0), Minimum_Key_In_Needy_Node);
- for Subtree_Number in 1..Needy_Node.Maximum_Subtree_Index loop
- Insert_Extra_Subtree (Left_Sibling, Minimum_Key_In_Left_Sibling, Needy_Node.Subtree (Subtree_Number),
- Needy_Node.Key ( Keys'Val ( Subtrees'Pos ( Subtree_Number ) ) ) );
- end loop;
- Destroy (Needy_Node);
- Delete_Subtree (Target_Node, Minimum_Key_In_Subtree, Path_Of_Descent);
-
- else
-
- Insert_Extra_Subtree (Needy_Node, Minimum_Key_In_Needy_Node, Right_Sibling.Subtree (0), Minimum_Key_In_Right_Sibling);
- for Subtree_Number in 1..Right_Sibling.Maximum_Subtree_Index loop
- Insert_Extra_Subtree (Needy_Node, Minimum_Key_In_Needy_Node, Right_Sibling.Subtree (Subtree_Number),
- Right_Sibling.Key ( Keys'Val ( Subtrees'Pos ( Subtree_Number))));
- end loop;
- Destroy (Right_Sibling);
- Delete_Subtree (Target_Node, Minimum_Key_In_Subtree, Path_Of_Descent + 1);
-
- end if;
-
- end Redistribute_Subtrees;
-
-
- begin -- procedure Descend_And_Delete
-
- if (Target_Node.Index_Node = False) then
-
- Delete_From_Leaf (Target_Node, Deletion_Type, Target_Key, Target_Non_Key_Object);
-
- else
-
- Path_Of_Descent := Determine_Path_Of_Descent (Target_Node, Target_Key);
-
- if (Path_Of_Descent = 0) then
- Descend_And_Delete ( Targeted_B_Plus_Tree, Target_Node.Subtree (0),
- Minimum_Key_In_Subtree, Deletion_Type, Target_Key, Target_Non_Key_Object );
- else
- Descend_And_Delete ( Targeted_B_Plus_Tree, Target_Node.Subtree (Path_Of_Descent),
- Target_Node.Key ( Keys'Val ( Subtrees'Pos (Path_Of_Descent) ) ),
- Deletion_Type, Target_Key, Target_Non_Key_Object );
- end if;
-
- if (Target_Node.Subtree (Path_Of_Descent) = null) then
- Delete_Subtree (Target_Node, Minimum_Key_In_Subtree, Path_Of_Descent);
- elsif (Target_Node.Subtree (Path_Of_Descent).Index_Node = True)
- and then (Target_Node.Subtree (Path_Of_Descent).Maximum_Subtree_Index < Minimum_Subtree_Number) then
- Redistribute_Subtrees (Target_Node, Minimum_Key_In_Subtree, Path_Of_Descent);
- end if;
-
- end if;
- end Descend_And_Delete;
- ----------------------------------------------------------------------------------------------------------------------------
- procedure Delete_Key (Targeted_B_Plus_Tree : in out B_Plus_Tree;
- Search_Key : in Key_Type ) is
-
- -- Raises Key_Does_Not_Exist_In_This_B_Plus_Tree
- -- or No_Keys_Currently_Exist_In_This_Empty_B_Plus_Tree, when appropriate...
- --
- -- The Non_Key_Item_Container associated with this key will be emptied via the Destroy_Contents procedure.
-
- Null_Non_Key_Information : Non_Key_Item_Type;
-
- begin -- procedure Delete_Key
- if Empty (Targeted_B_Plus_Tree) then
- raise No_Keys_Currently_Exist_In_This_Empty_B_Plus_Tree;
- else
- Descend_And_Delete (Targeted_B_Plus_Tree, Targeted_B_Plus_Tree.Root_Node,
- Targeted_B_Plus_Tree.Minimum_Key, Key, Search_Key, Null_Non_Key_Information);
- end if;
- end Delete_Key;
- ----------------------------------------------------------------------------------------------------------------------------
- procedure Delete_Item (Targeted_B_Plus_Tree : in out B_Plus_Tree;
- Key_Value : in Key_Type;
- Non_Key_Information : in Non_Key_Item_Type) is
-
- -- Raises Key_Does_Not_Exist_In_This_B_Plus_Tree
- -- or No_Keys_Currently_Exist_In_This_Empty_B_Plus_Tree, when appropriate...
-
- begin -- procedure Delete_Item
- if Empty (Targeted_B_Plus_Tree) then
- raise No_Keys_Currently_Exist_In_This_Empty_B_Plus_Tree;
- else
- Descend_And_Delete (Targeted_B_Plus_Tree, Targeted_B_Plus_Tree.Root_Node,
- Targeted_B_Plus_Tree.Minimum_Key, Non_Key_Object, Key_Value, Non_Key_Information);
- Targeted_B_Plus_Tree.Current_Leaf := null;
- if (Targeted_B_Plus_Tree.Root_Node.Maximum_Subtree_Index = 0) then
- if (Targeted_B_Plus_Tree.Root_Node.Subtree(0) /= null) then
- if (Targeted_B_Plus_Tree.Root_Node.Subtree(0).Index_Node = True) then
- declare
- Temp_Root : Internal_Node_Pointer := Targeted_B_Plus_Tree.Root_Node.Subtree(0);
- begin
- Destroy (Targeted_B_Plus_Tree.Root_Node);
- Targeted_B_Plus_Tree.Root_Node := Temp_Root;
- end;
- end if;
- else
- Destroy (Targeted_B_Plus_Tree.Root_Node);
- Destroy (Targeted_B_Plus_Tree);
- end if;
- end if;
- end if;
- end Delete_Item;
- ----------------------------------------------------------------------------------------------------------------------------
- function Get_First_Key (Targeted_B_Plus_Tree : in B_Plus_Tree) return Key_Type is
-
- -- Raises No_Keys_Currently_Exist_In_This_Empty_B_Plus_Tree when appropriate...
-
- begin -- function Get_First_Key
- if Empty (Targeted_B_Plus_Tree) then
- raise No_Keys_Currently_Exist_In_This_Empty_B_Plus_Tree;
- else
- return Targeted_B_Plus_Tree.Minimum_Key.all;
- end if;
- end Get_First_Key;
- ----------------------------------------------------------------------------------------------------------------------------
- function Get_Last_Key (Targeted_B_Plus_Tree : in B_Plus_Tree) return Key_Type is
-
- -- Raises No_Keys_Currently_Exist_In_This_Empty_B_Plus_Tree when appropriate...
-
- function Return_Last_Key (This_Subtree : Internal_Node_Pointer) return Key_Type is
-
- begin -- function Return_Last_Key
- if (This_Subtree.Index_Node = True) then
- return Return_Last_Key (This_Subtree.Subtree(This_Subtree.Maximum_Subtree_Index));
- else
- return This_Subtree.Key_Value.all;
- end if;
- end Return_Last_Key;
-
- begin -- function Get_Last_Key
- if Empty (Targeted_B_Plus_Tree) then
- raise No_Keys_Currently_Exist_In_This_Empty_B_Plus_Tree;
- else
- return Return_Last_Key (Targeted_B_Plus_Tree.Root_Node);
- end if;
- end Get_Last_Key;
- ----------------------------------------------------------------------------------------------------------------------------
- function Get_Leaf_Node (This_B_Plus_Tree : in B_Plus_Tree;
- Key_Value : in Key_Type ) return Internal_Node_Pointer is
-
- function Find_Leaf_Node (This_Subtree : in Internal_Node_Pointer;
- Key_Value : in Key_Type ) return Internal_Node_Pointer is
-
- Path_Number : Subtrees := 0;
-
- begin -- function Find_Leaf_Node
- if (This_Subtree.Index_Node = True) then
- while (Path_Number < This_Subtree.Maximum_Subtree_Index)
- and then not Less_Than (Key_Value, This_Subtree.Key(Keys'Val(Subtrees'Pos(Path_Number) + 1)).all) loop
- Path_Number := Path_Number + 1;
- end loop;
- return Find_Leaf_Node (This_Subtree.Subtree(Path_Number), Key_Value);
- else
- if Equal (This_Subtree.Key_Value.all, Key_Value) then
- return This_Subtree;
- else
- return null;
- end if;
- end if;
- end Find_Leaf_Node;
-
- begin -- function Get_Leaf_Node
- if not Empty (This_B_Plus_Tree) then
- if (This_B_Plus_Tree.Current_Leaf /= null)
- and then Equal (This_B_Plus_Tree.Current_Leaf.Key_Value.all, Key_Value) then
- return This_B_Plus_Tree.Current_Leaf;
- else
- return Find_Leaf_Node (This_B_Plus_Tree.Root_Node, Key_Value);
- end if;
- else
- return null;
- end if;
- end Get_Leaf_Node;
- ----------------------------------------------------------------------------------------------------------------------------
- function Key_Exists (Targeted_B_Plus_Tree : in B_Plus_Tree;
- Search_Key : in Key_Type ) return Boolean is
-
- begin -- function Key_Exists
- if not Empty (Targeted_B_Plus_Tree) then
- Targeted_B_Plus_Tree.Current_Leaf := Get_Leaf_Node (Targeted_B_Plus_Tree, Search_Key);
- return (Targeted_B_Plus_Tree.Current_Leaf /= null);
- else
- return False;
- end if;
- end Key_Exists;
- ----------------------------------------------------------------------------------------------------------------------------
- function Get_Item_Container (Targeted_B_Plus_Tree : in B_Plus_Tree;
- Search_Key : in Key_Type ) return Non_Key_Item_Container is
-
- -- Raises Key_Does_Not_Exist_In_This_B_Plus_Tree
- -- or No_Keys_Currently_Exist_In_This_Empty_B_Plus_Tree, when appropriate...
-
- begin -- function Get_Item_Container
- if Empty (Targeted_B_Plus_Tree) then
- raise No_Keys_Currently_Exist_In_This_Empty_B_Plus_Tree;
- else
- Targeted_B_Plus_Tree.Current_Leaf := Get_Leaf_Node (Targeted_B_Plus_Tree, Search_Key);
- if (Targeted_B_Plus_Tree.Current_Leaf = null) then
- raise Key_Does_Not_Exist_In_This_B_Plus_Tree;
- else
- return Targeted_B_Plus_Tree.Current_Leaf.Item_Container;
- end if;
- end if;
- end Get_Item_Container;
- ----------------------------------------------------------------------------------------------------------------------------
- function A_Preceding_Key_Exists (Targeted_B_Plus_Tree : in B_Plus_Tree;
- Search_Key : in Key_Type ) return Boolean is
-
- begin -- function A_Preceding_Key_Exists
- Targeted_B_Plus_Tree.Current_Leaf := Get_Leaf_Node (Targeted_B_Plus_Tree, Search_Key);
- return ( not Empty (Targeted_B_Plus_Tree)
- and then (Targeted_B_Plus_Tree.Current_Leaf /= null)
- and then (Targeted_B_Plus_Tree.Current_Leaf.Preceding_Leaf /= null) );
- end A_Preceding_Key_Exists;
- ----------------------------------------------------------------------------------------------------------------------------
- function Get_Preceding_Key (Targeted_B_Plus_Tree : in B_Plus_Tree;
- Search_Key : in Key_Type ) return Key_Type is
-
- -- Raises Key_Does_Not_Exist_In_This_B_Plus_Tree
- -- or No_Preceding_Key_Exists_In_This_B_Plus_Tree
- -- or No_Keys_Currently_Exist_In_This_Empty_B_Plus_Tree, when appropriate...
-
- Temp : Key_Type;
-
- begin -- function Get_Preceding_Key
- if not Empty (Targeted_B_Plus_Tree) then
- Targeted_B_Plus_Tree.Current_Leaf := Get_Leaf_Node (Targeted_B_Plus_Tree, Search_Key);
- if (Targeted_B_Plus_Tree.Current_Leaf /= null)
- and then (Targeted_B_Plus_Tree.Current_Leaf.Preceding_Leaf /= null) then
- return Targeted_B_Plus_Tree.Current_Leaf.Preceding_Leaf.Key_Value.all;
- elsif (Targeted_B_Plus_Tree.Current_Leaf.Preceding_Leaf = null) then
- raise No_Preceding_Key_Exists_In_This_B_Plus_Tree;
- elsif (Targeted_B_Plus_Tree.Current_Leaf = null) then
- raise Key_Does_Not_Exist_In_This_B_Plus_Tree;
- end if;
- else
- raise No_Keys_Currently_Exist_In_This_Empty_B_Plus_Tree;
- end if;
- end Get_Preceding_Key;
- ----------------------------------------------------------------------------------------------------------------------------
- function A_Following_Key_Exists (Targeted_B_Plus_Tree : in B_Plus_Tree;
- Search_Key : in Key_Type ) return Boolean is
-
- begin -- function A_Following_Key_Exists
- Targeted_B_Plus_Tree.Current_Leaf := Get_Leaf_Node (Targeted_B_Plus_Tree, Search_Key);
- return ( not Empty (Targeted_B_Plus_Tree)
- and then (Targeted_B_Plus_Tree.Current_Leaf /= null)
- and then (Targeted_B_Plus_Tree.Current_Leaf.Following_Leaf /= null) );
- end A_Following_Key_Exists;
- ----------------------------------------------------------------------------------------------------------------------------
- function Get_Following_Key (Targeted_B_Plus_Tree : in B_Plus_Tree;
- Search_Key : in Key_Type ) return Key_Type is
-
- -- Raises Key_Does_Not_Exist_In_This_B_Plus_Tree
- -- or No_Following_Key_Exists_In_This_B_Plus_Tree
- -- or No_Keys_Currently_Exist_In_This_Empty_B_Plus_Tree, when appropriate...
-
- begin -- function Get_Following_Key
- if not Empty (Targeted_B_Plus_Tree) then
- Targeted_B_Plus_Tree.Current_Leaf := Get_Leaf_Node (Targeted_B_Plus_Tree, Search_Key);
- if (Targeted_B_Plus_Tree.Current_Leaf /= null)
- and then (Targeted_B_Plus_Tree.Current_Leaf.Following_Leaf /= null) then
- return Targeted_B_Plus_Tree.Current_Leaf.Following_Leaf.Key_Value.all;
- elsif (Targeted_B_Plus_Tree.Current_Leaf.Following_Leaf = null) then
- raise No_Following_Key_Exists_In_This_B_Plus_Tree;
- elsif (Targeted_B_Plus_Tree.Current_Leaf = null) then
- raise Key_Does_Not_Exist_In_This_B_Plus_Tree;
- end if;
- else
- raise No_Keys_Currently_Exist_In_This_Empty_B_Plus_Tree;
- end if;
- end Get_Following_Key;
- ----------------------------------------------------------------------------------------------------------------------------
- procedure Assign (To_B_Plus_Tree : in out B_Plus_Tree;
- From_B_Plus_Tree : in B_Plus_Tree) is
-
- Last_Leaf : Internal_Node_Pointer;
-
- procedure Assign (To_Internal_Node : in out Internal_Node_Pointer;
- Minimum_Key_In_Subtree : out Key_Pointer;
- From_Internal_Node : in Internal_Node_Pointer) is
-
- begin -- procedure Assign
- To_Internal_Node := new Internal_Node (Index_Node => From_Internal_Node.Index_Node);
- if From_Internal_Node.Index_Node then
- To_Internal_Node.Maximum_Subtree_Index := From_Internal_Node.Maximum_Subtree_Index;
- Assign (To_Internal_Node.Subtree (0), Minimum_Key_In_Subtree, From_Internal_Node.Subtree (0));
- for Subtree_Number in 1..From_Internal_Node.Maximum_Subtree_Index loop
- Assign (To_Internal_Node.Subtree (Subtree_Number),
- To_Internal_Node.Key ( Keys'Val ( Subtrees'Pos (Subtree_Number) ) ),
- From_Internal_Node.Subtree (Subtree_Number));
- end loop;
- else
- To_Internal_Node.Preceding_Leaf := Last_Leaf;
- Last_Leaf.Following_Leaf := To_Internal_Node;
- To_Internal_Node.Key_Value := new Key_Type;
- Assign (To_Internal_Node.Key_Value.all, From_Internal_Node.Key_Value.all);
- Assign (To_Internal_Node.Item_Container, From_Internal_Node.Item_Container);
- Last_Leaf := To_Internal_Node;
- end if;
- end Assign;
-
- begin -- procedure Assign
- Destroy (To_B_Plus_Tree);
- if (From_B_Plus_Tree /= null) then
- To_B_Plus_Tree := new B_Plus_Tree_Descriptor;
- Assign (To_B_Plus_Tree.Root_Node, To_B_Plus_Tree.Minimum_Key, From_B_Plus_Tree.Root_Node);
- To_B_Plus_Tree.Current_Leaf := Get_Leaf_Node (To_B_Plus_Tree, From_B_Plus_Tree.Current_Leaf.Key_Value.all);
- To_B_Plus_Tree.Number_Of_Keys_Stored := From_B_Plus_Tree.Number_Of_Keys_Stored;
- end if;
- end Assign;
- ----------------------------------------------------------------------------------------------------------------------------
-
-
- end BP_Tree;
- --::::::::::
- --cisc.bdy
- --::::::::::
- package body case_insensitive_string_comparison is
-
- --| Overview
- --| Strings are compared one character at a time, stopping as soon as
- --| possible.
-
- --| Programmer: M. Gordon
-
- ------------------------------------------------------------------------
-
- Up_ConvertArray: array(Character) of Character;
- Down_ConvertArray: array(Character) of Character;
- Difference: constant := Character'pos('a') - Character'pos('A');
-
- function toUpper(C: character) return character is
- begin
- return Up_ConvertArray(C);
-
- end toUpper;
-
-
- function upCase( --| Return copy of S with all characters lower case
- S: String
- ) return String
- is
- R: String(S'Range) := S;
-
- begin
- for i in R'Range loop
- R(i) := toUpper(R(i));
- end loop;
- return R;
-
- end upCase;
-
-
- procedure upCase( --| Convert all characters in S to lower case
- S: in out String
- ) is
-
- begin
- for i in S'Range loop
- S(i) := toUpper(S(i));
- end loop;
-
- end upCase;
-
- ------------------------------------------------------------------------
-
- function toLower(C: character) return character is
- begin
- return Down_ConvertArray(C);
-
- end toLower;
-
-
- function downCase( --| Return copy of S with all characters lower case
- S: String
- ) return String
- is
- R: String(S'Range) := S;
-
- begin
- for i in R'Range loop
- R(i) := toLower(R(i));
- end loop;
- return R;
-
- end downCase;
-
- procedure downCase( --| Convert all characters in S to lower case
- S: in out String
- ) is
-
- begin
- for i in S'Range loop
- S(i) := toLower(S(i));
- end loop;
-
- end downCase;
-
- ------------------------------------------------------------------------
-
- function compare( --| Compare two strings
- P, Q: String
- ) return integer
- is
- QI: natural;
- PC, QC: character;
-
- begin
- QI := Q'First;
- for PI in P'First .. P'Last loop
- if QI > Q'Last then
- return 1; -- Q ran out before P did.
- end if;
- PC := toUpper(P(PI));
- QC := toUpper(Q(QI));
- if PC /= QC then
- return character'pos(PC) - character'pos(QC);
- end if;
- QI := QI + 1;
- end loop;
- return P'Length - Q'Length; -- Equal so far: longer string is greater
-
- end compare;
-
- ------------------------------------------------------------------------
-
- function equal(
- P, Q: String
- ) return boolean is
- begin
- return compare(P, Q) = 0;
-
- end equal;
-
- ------------------------------------------------------------------------
-
- function less(
- P, Q: String
- ) return boolean is
- begin
- return compare(P, Q) < 0;
- end less;
-
-
- function less_or_equal(
- P, Q: String
- ) return boolean is
- begin
- return compare(P, Q) <= 0;
- end less_or_equal;
-
-
- ------------------------------------------------------------------------
-
- function greater(
- P, Q: String
- ) return boolean is
- begin
- return compare(P, Q) > 0;
- end greater;
-
- function greater_or_equal(
- P, Q: String
- ) return boolean is
- begin
- return compare(P, Q) >= 0;
- end greater_or_equal;
-
- ------------------------------------------------------------------------
-
- begin
-
- for I in Character loop
- case I is
- when 'a' .. 'z' =>
- Up_ConvertArray(I) := Character'val(Character'pos(I) - Difference);
- when others =>
- Up_ConvertArray(I) := I;
- end case;
- end loop;
-
- for I in Character loop
- case I is
- when 'A' .. 'Z' =>
- Down_ConvertArray(I) := Character'val(Character'pos(I) + Difference);
- when others =>
- Down_ConvertArray(I) := I;
- end case;
- end loop;
-
- end case_insensitive_string_comparison;
- --::::::::::
- --cset.bdy
- --::::::::::
- package body CHARACTER_SET is
-
- function TO_LOWER (CH : in CHARACTER) return CHARACTER is
- begin
- return LOWER (CH);
- end TO_LOWER;
-
- procedure TO_LOWER (CH : in out CHARACTER) is
- begin
- CH := LOWER (CH);
- end TO_LOWER;
-
- procedure TO_LOWER (STR : in out STRING) is
- begin
- for I in STR'FIRST .. STR'LAST loop
- STR (I) := LOWER (STR (I));
- end loop;
- end TO_LOWER;
-
- function TO_UPPER (CH : in CHARACTER) return CHARACTER is
- begin
- return UPPER (CH);
- end TO_UPPER;
-
- procedure TO_UPPER (CH : in out CHARACTER) is
- begin
- CH := UPPER (CH);
- end TO_UPPER;
-
- procedure TO_UPPER (STR : in out STRING) is
- begin
- for I in STR'FIRST .. STR'LAST loop
- STR (I) := UPPER (STR (I));
- end loop;
- end TO_UPPER;
-
- function CC_NAME_2 (CH : CHARACTER) return CONTROL_CHARACTER_NAME_2 is
- NAME : CONTROL_CHARACTER_NAME_2;
- begin
- case CH is
- when ASCII.NUL => NAME := "^@";
- when ASCII.SOH => NAME := "^A";
- when ASCII.STX => NAME := "^B";
- when ASCII.ETX => NAME := "^C";
- when ASCII.EOT => NAME := "^D";
- when ASCII.ENQ => NAME := "^E";
- when ASCII.ACK => NAME := "^F";
- when ASCII.BEL => NAME := "^G";
- when ASCII.BS => NAME := "^H";
- when ASCII.HT => NAME := "^I";
- when ASCII.LF => NAME := "^J";
- when ASCII.VT => NAME := "^K";
- when ASCII.FF => NAME := "^L";
- when ASCII.CR => NAME := "^M";
- when ASCII.SO => NAME := "^N";
- when ASCII.SI => NAME := "^O";
- when ASCII.DLE => NAME := "^P";
- when ASCII.DC1 => NAME := "^Q";
- when ASCII.DC2 => NAME := "^R";
- when ASCII.DC3 => NAME := "^S";
- when ASCII.DC4 => NAME := "^T";
- when ASCII.NAK => NAME := "^U";
- when ASCII.SYN => NAME := "^V";
- when ASCII.ETB => NAME := "^W";
- when ASCII.CAN => NAME := "^X";
- when ASCII.EM => NAME := "^Y";
- when ASCII.SUB => NAME := "^Z";
- when ASCII.ESC => NAME := "^[";
- when ASCII.FS => NAME := "^\";
- when ASCII.GS => NAME := "^]";
- when ASCII.RS => NAME := "^^";
- when ASCII.US => NAME := "^_";
- when ASCII.DEL => NAME := "^`";
- when others =>
- NAME := " ";
- NAME (2) := CH;
- end case;
- return NAME;
- end CC_NAME_2;
-
- function CC_NAME_3 (CH : CHARACTER) return CONTROL_CHARACTER_NAME_3 is
- NAME : CONTROL_CHARACTER_NAME_3;
- begin
- case CH is
- when ASCII.NUL => NAME := "NUL";
- when ASCII.SOH => NAME := "SOH";
- when ASCII.STX => NAME := "STX";
- when ASCII.ETX => NAME := "ETX";
- when ASCII.EOT => NAME := "EOT";
- when ASCII.ENQ => NAME := "ENQ";
- when ASCII.ACK => NAME := "ACK";
- when ASCII.BEL => NAME := "BEL";
- when ASCII.BS => NAME := "BS ";
- when ASCII.HT => NAME := "HT ";
- when ASCII.LF => NAME := "LF ";
- when ASCII.VT => NAME := "VT ";
- when ASCII.FF => NAME := "FF ";
- when ASCII.CR => NAME := "CR ";
- when ASCII.SO => NAME := "SO ";
- when ASCII.SI => NAME := "SI ";
- when ASCII.DLE => NAME := "DLE";
- when ASCII.DC1 => NAME := "DC1";
- when ASCII.DC2 => NAME := "DC2";
- when ASCII.DC3 => NAME := "DC3";
- when ASCII.DC4 => NAME := "DC4";
- when ASCII.NAK => NAME := "NAK";
- when ASCII.SYN => NAME := "SYN";
- when ASCII.ETB => NAME := "ETB";
- when ASCII.CAN => NAME := "CAN";
- when ASCII.EM => NAME := "EM ";
- when ASCII.SUB => NAME := "SUB";
- when ASCII.ESC => NAME := "ESC";
- when ASCII.FS => NAME := "FS ";
- when ASCII.GS => NAME := "GS ";
- when ASCII.RS => NAME := "RS ";
- when ASCII.US => NAME := "US ";
- when ASCII.DEL => NAME := "DEL";
- when others =>
- NAME := " ";
- NAME (2) := CH;
- end case;
- return NAME;
- end CC_NAME_3;
- end CHARACTER_SET;
- --::::::::::
- --cssc.bdy
- --::::::::::
- package body case_sensitive_string_comparison is
-
- --| Overview
- --| Strings are compared one character at a time, stopping as soon as
- --| possible.
-
- --| Programmer: M. Gordon
-
- ------------------------------------------------------------------------
-
- function compare( --| Compare two strings
- P, Q: String
- ) return integer
- is
- QI: natural;
-
- begin
- QI := Q'First;
- for PI in P'First .. P'Last loop
- if QI > Q'Last then
- return 1; -- Q ran out before P did.
- end if;
- if P(PI) /= Q(QI) then
- return character'pos(P(PI)) - character'pos(Q(QI));
- end if;
- QI := QI + 1;
- end loop;
- return P'Length - Q'Length; -- Equal so far: longer string is greater
-
- end compare;
-
- ------------------------------------------------------------------------
-
- function equal(
- P, Q: String
- ) return boolean is
- begin
- return P = Q;
-
- end equal;
-
- ------------------------------------------------------------------------
-
- function less(
- P, Q: String
- ) return boolean is
- begin
- return P < Q;
- end less;
-
-
- function less_or_equal(
- P, Q: String
- ) return boolean is
- begin
- return P <= Q;
- end less_or_equal;
-
-
- ------------------------------------------------------------------------
-
- function greater(
- P, Q: String
- ) return boolean is
- begin
- return P > Q;
- end greater;
-
- function greater_or_equal(
- P, Q: String
- ) return boolean is
- begin
- return P >= Q;
- end greater_or_equal;
-
- ------------------------------------------------------------------------
-
- end case_sensitive_string_comparison;
- --::::::::::
- --cstrings.bdy
- --::::::::::
- -- ********************************************************
- -- * *
- -- * CStrings * BODY
- -- * *
- -- ********************************************************
- package body CStrings is
- --| Notes
- --| Reference Sun Release 4.0 man pages on "strings".
-
- Work : STRING(1..Max_String_Length);
- Work2 : STRING(1..Max_String_Length);
- Work3 : STRING(1..Max_String_Length);
-
- Charpos_LC_A : constant := CHARACTER'POS('a');
- Charpos_UC_A : constant := CHARACTER'POS('A');
-
- -- ...................................................
- -- . .
- -- . CStrings.Toupper . SPEC & BODY
- -- . .
- -- ...................................................
- function Toupper (Item : in CHARACTER) return CHARACTER is
- Result : CHARACTER := Item;
- begin
- if Item in 'a' .. 'z' then
- Result := CHARACTER'VAL(CHARACTER'POS(Item) - Charpos_LC_A +
- Charpos_UC_A);
- end if;
- return Result;
- end Toupper;
- pragma inline (Toupper);
-
- -- ...................................................
- -- . .
- -- . CStrings.Char_is_in_String . SPEC & BODY
- -- . .
- -- ...................................................
- function Char_is_in_String (Ch : in CHARACTER;
- S : in STRING) return BOOLEAN is
- begin
- return Strchr(S, Ch) /= 0;
- end Char_is_in_String;
- pragma inline (Char_is_in_String);
-
- -- ...................................................
- -- . .
- -- . CStrings.Copy . SPEC & BODY
- -- . .
- -- ...................................................
- procedure Copy (Source : in STRING;
- Destination : out STRING;
- D_Start : in NATURAL) is
- --| Note
- --| Any exception raised here (probably CONSTRAINT_ERROR)
- --| is to be handled by the caller.
- S : NATURAL;
- begin
- S := Strlen(Source);
- if S > 0 then
- Destination(D_Start..D_Start+S-1)
- := Source(Source'FIRST .. Source'FIRST+S-1);
- end if;
- Destination(D_Start+S) := ASCII.NUL;
- end Copy;
- pragma inline (Copy);
-
- -- ...................................................
- -- . .
- -- . CStrings.Make_Cstring . BODY
- -- . .
- -- ...................................................
- procedure Make_Cstring (From : in STRING;
- To : out STRING) is
- begin
- To(To'FIRST .. To'FIRST + From'LENGTH - 1)
- := From;
- To(To'FIRST + From'LENGTH) := ASCII.NUL;
- exception
- when others => raise LENGTH_ERROR;
- end Make_Cstring;
-
- -- ...................................................
- -- . .
- -- . CStrings.Make_Cstring . BODY
- -- . .
- -- ...................................................
- procedure Make_Cstring (From_To : in out STRING;
- Index : in NATURAL) is
- begin
- From_To(Index) := ASCII.NUL;
- exception
- when others => raise LENGTH_ERROR;
- end Make_Cstring;
-
- -- ...................................................
- -- . .
- -- . CStrings.Ada_String . BODY
- -- . .
- -- ...................................................
- function Ada_String (From : in STRING) return STRING is
- begin
- return From(From'FIRST .. From'FIRST + Strlen(From) - 1);
- end Ada_String;
-
- -- ...................................................
- -- . .
- -- . CStrings.Strcat . BODY
- -- . .
- -- ...................................................
- procedure Strcat (To : in out STRING;
- From : in STRING) is
- begin
- Copy(To, Work, Work'FIRST);
- Copy(From, Work, Work'FIRST + Strlen(To));
- Copy(Work, To, To'FIRST);
- exception
- when others => raise LENGTH_ERROR;
- end Strcat;
-
- -- ...................................................
- -- . .
- -- . CStrings.Strcat . BODY
- -- . .
- -- ...................................................
- function Strcat (From_Part_1 : in STRING;
- From_Part_2 : in STRING) return STRING is
- --| Note
- --| Buffer Work2 is used because procedure Strcat uses
- --| buffer Work.
- begin
- Strcpy(From_Part_1, Work2);
- Strcat(Work2, From_Part_2);
- return Work2(Work2'FIRST .. Work2'FIRST + Strlen(Work2));
- exception
- when others => raise LENGTH_ERROR;
- end Strcat;
-
- -- ...................................................
- -- . .
- -- . CStrings.Strncat . BODY
- -- . .
- -- ...................................................
- procedure Strncat (To : in out STRING;
- From : in STRING;
- Length : in NATURAL) is
- --| Note
- --| Buffer Work2 is used because procedure Strcat uses
- --| buffer Work.
- begin
- Copy(From, Work2, Work2'FIRST);
- Work2(Work2'FIRST + Length) := ASCII.NUL;
- Strcat(To, Work2);
- exception
- when others => raise LENGTH_ERROR;
- end Strncat;
-
- -- ...................................................
- -- . .
- -- . CStrings.Strncat . BODY
- -- . .
- -- ...................................................
- function Strncat (To : in STRING;
- From : in STRING;
- Length : in NATURAL) return STRING is
- --| Note
- --| Buffer Work3 is used because procedure Strcat uses
- --| buffer Work and procedure Strncat uses buffer Work2.
- begin
- Copy(To, Work3, Work3'FIRST);
- Strncat(Work3, From, Length);
- return Work3(Work3'FIRST .. Work3'FIRST + Strlen(Work3));
- exception
- when others => raise LENGTH_ERROR;
- end Strncat;
-
- -- ...................................................
- -- . .
- -- . CStrings.Strcmp . BODY
- -- . .
- -- ...................................................
- function Strcmp (String1 : in STRING;
- String2 : in STRING)
- return COMPARISON_RESULT is
- Result : COMPARISON_RESULT := EQUAL_TO;
- S1 : NATURAL := String1'FIRST;
- S2 : NATURAL := String2'FIRST;
- Loop_Exit : BOOLEAN;
- begin
- if String1'LENGTH > 0 and String2'LENGTH > 0 then
-
- -- Both strings are not empty (contain at least
- -- ASCII.NUL)
- while String1(S1) /= ASCII.NUL loop
-
- -- loop thru String1, comparing it char-for-char
- -- with String2
- Loop_Exit := FALSE; -- indicates abnormal loop exit
- if String1(S1) /= String2(S2) then
-
- -- if the two chars are not the same,
- -- then we can determine a result
- if String1(S1) < String2(S2) then
- Result := LESS_THAN;
- else
- Result := GREATER_THAN;
- end if;
- exit;
- end if;
-
- -- the two strings are the same so far, so
- -- continue advancing thru them
- S1 := S1 + 1;
- S2 := S2 + 1;
-
- -- done if we are past the ends of both strings
- exit when S1 > String1'LAST and S2 > String2'LAST;
-
- -- we can determine the result if we are past the
- -- end of String1 but not String2
- if S1 > String1'LAST then
- if String2(S2) /= ASCII.NUL then
- Result := LESS_THAN;
- end if;
- exit;
- end if;
-
- -- we can determine the result if we are past the
- -- end of String2 but not String1
- if S2 > String2'LAST then
- if String1(S1) /= ASCII.NUL then
- Result := GREATER_THAN;
- end if;
- exit;
- end if;
- Loop_Exit := TRUE; -- indicates normal exit of loop
- end loop;
-
- -- we have exited the loop either normally or abnormally
- -- (abnormally is via an exit statement); if normally,
- -- then we have reached the end of String1 and the result
- -- is EQUAL_TO unless we have also reached the end of
- -- String2
- if Loop_Exit then
- if String2(S2) /= ASCII.NUL then
- Result := LESS_THAN;
- end if;
- end if;
- else
-
- -- one of the strings is empty, so determine the
- -- result (Result is already EQUAL_TO, so if either
- -- string has some length, then Result changes)
- if String1'LENGTH > 0 then
- Result := GREATER_THAN;
- elsif String2'LENGTH > 0 then
- Result := LESS_THAN;
- end if;
- end if;
-
- -- Result is the answer
- return Result;
- end Strcmp;
-
- -- ...................................................
- -- . .
- -- . CStrings.Strncmp . BODY
- -- . .
- -- ...................................................
- function Strncmp (String1 : in STRING;
- String2 : in STRING;
- Length : in NATURAL)
- return COMPARISON_RESULT is
- Result : COMPARISON_RESULT := EQUAL_TO;
- S1 : NATURAL := String1'FIRST;
- S2 : NATURAL := String2'FIRST;
- Count : NATURAL := Length;
- Loop_Exit : BOOLEAN;
- begin
- if (String1'LENGTH > 0 and String2'LENGTH > 0) and
- (Count > 0) then
-
- -- Both strings are not empty (contain at least
- -- ASCII.NUL) and Count is non-zero
- while String1(S1) /= ASCII.NUL loop
-
- -- loop thru String1, comparing it char-for-char
- -- with String2
- Loop_Exit := FALSE; -- indicates abnormal loop exit
- if String1(S1) /= String2(S2) then
-
- -- if the two chars are not the same,
- -- then we can determine a result
- if String1(S1) < String2(S2) then
- Result := LESS_THAN;
- else
- Result := GREATER_THAN;
- end if;
- exit;
- end if;
-
- -- the two strings are the same so far, so
- -- continue advancing thru them
- S1 := S1 + 1;
- S2 := S2 + 1;
-
- -- done if we have exhausted the count
- Count := Count - 1;
- exit when Count = 0;
-
- -- done if we are past the ends of both strings
- exit when S1 > String1'LAST and S2 > String2'LAST;
-
- -- we can determine the result if we are past the
- -- end of String1 but not String2
- if S1 > String1'LAST then
- if String2(S2) /= ASCII.NUL then
- Result := LESS_THAN;
- end if;
- exit;
- end if;
-
- -- we can determine the result if we are past the
- -- end of String2 but not String1
- if S2 > String2'LAST then
- if String1(S2) /= ASCII.NUL then
- Result := GREATER_THAN;
- end if;
- exit;
- end if;
- Loop_Exit := TRUE; -- indicates normal exit of loop
- end loop;
-
- -- we have exited the loop either normally or abnormally
- -- (abnormally is via an exit statement); if normally,
- -- then we have reached the end of String1 and the result
- -- is EQUAL_TO unless we have also reached the end of
- -- String2
- if Loop_Exit and (Count > 0) then
- if String2(S2) /= ASCII.NUL then
- Result := LESS_THAN;
- end if;
- end if;
- else
-
- -- one of the strings is empty, so determine the
- -- result (Result is already EQUAL_TO, so if either
- -- string has some length, then Result changes)
- if Count > 0 then -- proceed only if Count > 0
- if String1'LENGTH > 0 then
- Result := GREATER_THAN;
- elsif String2'LENGTH > 0 then
- Result := LESS_THAN;
- end if;
- end if;
- end if;
-
- -- Result is the answer
- return Result;
- end Strncmp;
-
- -- ...................................................
- -- . .
- -- . CStrings.Strcasecmp . BODY
- -- . .
- -- ...................................................
- function Strcasecmp (String1 : in STRING;
- String2 : in STRING)
- return COMPARISON_RESULT is
- --| Notes
- --| This is not commented well because the same
- --| comments as in Strcmp apply except that Toupper
- --| is always called on the characters being compared
- Result : COMPARISON_RESULT := EQUAL_TO;
- S1 : NATURAL := String1'FIRST;
- S2 : NATURAL := String2'FIRST;
- Loop_Exit : BOOLEAN;
- begin
- if String1'LENGTH > 0 and String2'LENGTH > 0 then
- while String1(S1) /= ASCII.NUL loop
- Loop_Exit := FALSE;
- if Toupper(String1(S1)) /= Toupper(String2(S2)) then
- if Toupper(String1(S1)) < Toupper(String2(S2)) then
- Result := LESS_THAN;
- else
- Result := GREATER_THAN;
- end if;
- exit;
- end if;
- S1 := S1 + 1;
- S2 := S2 + 1;
- exit when S1 > String1'LAST and S2 > String2'LAST;
- if S1 > String1'LAST then
- if String2(S2) /= ASCII.NUL then
- Result := LESS_THAN;
- end if;
- exit;
- end if;
- if S2 > String2'LAST then
- if String1(S1) /= ASCII.NUL then
- Result := GREATER_THAN;
- end if;
- exit;
- end if;
- Loop_Exit := TRUE;
- end loop;
- if Loop_Exit then
- if String2(S2) /= ASCII.NUL then
- Result := LESS_THAN;
- end if;
- end if;
- else
- if String1'LENGTH > 0 then
- Result := GREATER_THAN;
- elsif String2'LENGTH > 0 then
- Result := LESS_THAN;
- end if;
- end if;
- return Result;
- end Strcasecmp;
-
- -- ...................................................
- -- . .
- -- . CStrings.Strncasecmp . BODY
- -- . .
- -- ...................................................
- function Strncasecmp (String1 : in STRING;
- String2 : in STRING;
- Length : in NATURAL)
- return COMPARISON_RESULT is
- --| Notes
- --| This is not commented well because the same
- --| comments as in Strncmp apply except that Toupper
- --| is always called on the characters being compared
- Result : COMPARISON_RESULT := EQUAL_TO;
- S1 : NATURAL := String1'FIRST;
- S2 : NATURAL := String2'FIRST;
- Count : NATURAL := Length;
- Loop_Exit : BOOLEAN;
- begin
- if (String1'LENGTH > 0 and String2'LENGTH > 0) and
- (Count > 0) then
- while String1(S1) /= ASCII.NUL loop
- Loop_Exit := FALSE;
- if Toupper(String1(S1)) /= Toupper(String2(S2)) then
- if Toupper(String1(S1)) < Toupper(String2(S2)) then
- Result := LESS_THAN;
- else
- Result := GREATER_THAN;
- end if;
- exit;
- end if;
- S1 := S1 + 1;
- S2 := S2 + 1;
- Count := Count - 1;
- exit when Count = 0;
- exit when S1 > String1'LAST and S2 > String2'LAST;
- if S1 > String1'LAST then
- if String2(S2) /= ASCII.NUL then
- Result := LESS_THAN;
- end if;
- exit;
- end if;
- if S2 > String2'LAST then
- if String1(S1) /= ASCII.NUL then
- Result := GREATER_THAN;
- end if;
- exit;
- end if;
- Loop_Exit := TRUE;
- end loop;
- if Loop_Exit and (Count > 0) then
- if String2(S2) /= ASCII.NUL then
- Result := LESS_THAN;
- end if;
- end if;
- else
- if Count > 0 then
- if String1'LENGTH > 0 then
- Result := GREATER_THAN;
- elsif String2'LENGTH > 0 then
- Result := LESS_THAN;
- end if;
- end if;
- end if;
- return Result;
- end Strncasecmp;
-
- -- ...................................................
- -- . .
- -- . CStrings.Strcpy . BODY
- -- . .
- -- ...................................................
- procedure Strcpy (From : in STRING;
- To : out STRING) is
- begin
- Copy(From, To, To'FIRST);
- exception
- when others => raise LENGTH_ERROR;
- end Strcpy;
-
- -- ...................................................
- -- . .
- -- . CStrings.Strncpy . BODY
- -- . .
- -- ...................................................
- procedure Strncpy (From : in STRING;
- To : out STRING;
- Length : in NATURAL) is
- S : NATURAL := From'FIRST;
- D : NATURAL := To'FIRST;
- Count : NATURAL := Length;
- begin
-
- -- do not attempt copy if From is empty
- if From'LENGTH > 0 then
-
- -- perform a char-for-char copy, checking for
- -- ASCII.NUL, end of From buffer, and end of Count
- while From(S) /= ASCII.NUL loop
- To(D) := From(S);
- D := D + 1;
- S := S + 1;
- exit when S > From'LAST;
- Count := Count - 1;
- exit when Count = 0;
- end loop;
- end if;
- To(D) := ASCII.NUL;
- exception
- when others => raise LENGTH_ERROR;
- end Strncpy;
-
- -- ...................................................
- -- . .
- -- . CStrings.Strlen . BODY
- -- . .
- -- ...................................................
- function Strlen (String1 : in STRING) return NATURAL is
- Result : NATURAL := 0;
- S : NATURAL := String1'FIRST;
- begin
- if S <= String1'LAST then
- while String1(S) /= ASCII.NUL loop
- Result := Result + 1;
- S := S + 1;
- exit when S > String1'LAST;
- end loop;
- end if;
- return Result;
- end Strlen;
-
- -- ...................................................
- -- . .
- -- . CStrings.Strchr . BODY
- -- . .
- -- ...................................................
- function Strchr (String1 : in STRING;
- Char1 : in CHARACTER) return NATURAL is
- Result : NATURAL := 0;
- S : NATURAL := String1'FIRST;
- begin
- if String1'LENGTH > 0 then
- -- if String1 is not empty, do char-by-char
- -- compare
- while String1(S) /= ASCII.NUL loop
- if String1(S) = Char1 then
- Result := S;
- exit;
- end if;
- S := S + 1;
- exit when S > String1'LAST;
- end loop;
- end if;
- return Result;
- end Strchr;
-
- -- ...................................................
- -- . .
- -- . CStrings.Strrchr . BODY
- -- . .
- -- ...................................................
- function Strrchr (String1 : in STRING;
- Char1 : in CHARACTER) return NATURAL is
- Result : NATURAL := 0;
- S : NATURAL;
- begin
- S := Strlen(String1);
- if S > 0 then
- -- search only if the string is not empty
- S := String1'FIRST + Strlen(String1) - 1; -- index of last char
- loop
- if String1(S) = Char1 then
- Result := S;
- exit;
- end if;
- exit when S = String1'FIRST;
- S := S - 1;
- end loop;
- end if;
- return Result;
- end Strrchr;
-
- -- ...................................................
- -- . .
- -- . CStrings.Strpbrk . BODY
- -- . .
- -- ...................................................
- function Strpbrk (String1 : in STRING;
- String2 : in STRING) return NATURAL is
- Result : NATURAL := 0;
- S1 : NATURAL := String1'FIRST;
- begin
- if String1'LENGTH > 0 then
- -- search only if String1 is not empty
- while String1(S1) /= ASCII.NUL loop
- if Char_is_in_String (String1(S1), String2) then
- Result := S1;
- exit;
- end if;
- S1 := S1 + 1;
- exit when S1 > String1'LAST;
- end loop;
- end if;
- return Result;
- end Strpbrk;
-
- -- ...................................................
- -- . .
- -- . CStrings.Strspn . BODY
- -- . .
- -- ...................................................
- function Strspn (String1 : in STRING;
- String2 : in STRING) return NATURAL is
- S1 : NATURAL := String1'FIRST;
- Result : NATURAL := 0;
- begin
- if String1'LENGTH > 0 then
-
- -- search only if String1 is not empty
- while String1(S1) /= ASCII.NUL loop
- if Char_is_in_String (String1(S1), String2) then
- Result := 1;
- S1 := S1 + 1;
- exit;
- end if;
- S1 := S1 + 1;
- exit when S1 > String1'LAST;
- end loop;
-
- -- at this point, Result=1 if we found a char
- if Result = 1 and S1 <= String1'LAST then
- -- we have found one of the chars and are not done,
- -- so look for rest of the chars
- while String1(S1) /= ASCII.NUL loop
- if Char_is_in_String (String1(S1), String2) then
- Result := Result + 1;
- else
- exit;
- end if;
- S1 := S1 + 1;
- exit when S1 > String1'LAST;
- end loop;
- end if;
- end if;
- return Result;
- end Strspn;
-
- -- ...................................................
- -- . .
- -- . CStrings.Strcspn . BODY
- -- . .
- -- ...................................................
- function Strcspn (String1 : in STRING;
- String2 : in STRING) return NATURAL is
- S1 : NATURAL := String1'First;
- Result : NATURAL := 0;
- begin
- if String1'LENGTH > 0 then
-
- -- do this only if String1 is not empty
- while String1(S1) /= ASCII.NUL loop
- if not Char_is_in_String (String1(S1), String2) then
- Result := 1;
- S1 := S1 + 1;
- exit;
- end if;
- S1 := S1 + 1;
- exit when S1 > String1'LAST;
- end loop;
-
- -- Result=1 means we have not found one of the chars
- if Result = 1 and S1 <= String1'LAST then
-
- -- look for limit to non-matching string
- while String1(S1) /= ASCII.NUL loop
- if not Char_is_in_String (String1(S1), String2) then
- Result := Result + 1;
- else
- exit;
- end if;
- S1 := S1 + 1;
- exit when S1 > String1'LAST;
- end loop;
- end if;
- end if;
- return Result;
- end Strcspn;
-
- -- ...................................................
- -- . .
- -- . CStrings.Strtok . BODY
- -- . .
- -- ...................................................
- procedure Strtok (Target : in STRING;
- Start : in out NATURAL;
- Delimiters : in STRING;
- Next_Token : out STRING) is
- Next_Rover : NATURAL := Next_Token'FIRST;
- begin
- if Start > Target'LAST then
-
- -- Done if past the end of the string
- Next_Token(Next_Rover) := ASCII.NUL;
- else
-
- -- skip over leading delimiters
- while Start <= Target'LAST and then
- (Char_is_in_String (Target(Start), Delimiters) and
- Target(Start) /= ASCII.NUL) loop
- Start := Start + 1;
- end loop;
-
- -- Start is now index of first char, so begin extraction
- -- of token into Next_Token buffer
- while Start <= Target'LAST and then
- (not Char_is_in_String (Target(Start), Delimiters) and
- Target(Start) /= ASCII.NUL) loop
- Next_Token(Next_Rover) := Target(Start);
- Next_Rover := Next_Rover + 1;
- Start := Start + 1;
- exit when Start > Target'LAST;
- end loop;
-
- -- Start is either index of delimiter after last char
- -- of token or index of ASCII.NUL after Target string
- Next_Token(Next_Rover) := ASCII.NUL;
- end if;
- exception
- when others => raise LENGTH_ERROR;
- end Strtok;
-
- end CStrings;
- --::::::::::
- --darray.bdy
- --::::::::::
- with unchecked_deallocation;
-
- package body darray_pkg is
-
- -- Utilities:
-
- procedure free_array_ptr is
- new unchecked_deallocation(array_type, array_ptr);
-
- procedure free_darray is
- new unchecked_deallocation(darray_info, darray);
-
- function down_index(i: integer;
- d: darray)
- return integer;
-
- --| Raises: out_of_bounds
- --| Effects:
- --| Map from abstraction indices to representation indices.
- --| Raises out_of_bounds iff either is_empty(d) or i is not in
- --| d.first..last(d).
- --| Requires: d must be initialized.
-
- procedure initialization_check(d: darray);
-
- --| Raises: uninitialized_darray
- --| Effects:
- --| Returns normally iff d has been the target of a create, copy,
- --| or array_to_darray operation, and has not since been destroyed.
- --| Otherwise, raises uninitialized_darray.
- --| This procedure will not detect the case where another object
- --| sharing the same darray value has been destroyed; this is
- --| erroneous use.
-
- procedure expand(d: in out darray);
-
- --| Effects:
- --| Allocates additional space in d.arr. The old contents of d.arr
- --| are copied to a slice of the new array. The expansion amount is
- --| a percentage (d.expand_percent) of currently allocated space.
- --| Sets d.first_idx and d.last_idx to appropriate positions in the
- --| new array; these positions are selected according to the
- --| expected distribution of add_highs/add_lows (d.high_percent).
- --| Requires: d must be initialized.
-
- procedure contract(d: in out darray);
-
- --| Effects:
- --| Checks whether d.arr consumes too much space in proportion to
- --| the slice that is being used to hold the darray elements. If
- --| so, halves the size of d.arr. The old contents of d.arr are
- --| copied to a slice of the new array. Sets d.first_idx and
- --| and d.last_idx to appropriate positions in the new array; these
- --| positions are selected according to the expected distribution of
- --| add_highs/add_lows (d.high_percent).
- --| Requires: d must be initialized and nonempty.
-
- procedure reallocate(d: in out darray;
- new_length: in positive);
-
- --| Raises: out_of_bounds
- --| Effects:
- --| Replaces d.arr with a pointer to an array of length new_length,
- --| fills a slice of this array with the old contents of d.arr, and
- --| adjusts d.first_idx and d.last_idx appropriately. Everything is
- --| done according to d.high_percent. Used by both expand/contract.
- --| Raises out_of_bounds iff new_length < length(d).
- --| Requires: d must be initialized.
-
- procedure determine_position(array_length: in positive;
- slice_length: in natural;
- high_percent: in positive;
- first_idx: out positive;
- last_idx: out natural);
-
- --| Raises: out_of_bounds
- --| Effects:
- --| Determines the appropriate position of a slice of length
- --| slice_length in an array with range 1..array_length. This
- --| position is calculated according to the high_percent parameter.
- --| Raises out_of_bounds iff slice_length > array_length.
- --| Used by create, array_to_darray, reallocate.
-
-
- -- Constructors:
-
- procedure create(first: in integer := 1;
- predict: in positive := default_predict;
- high_percent: in positive := default_high;
- expand_percent: in positive := default_expand;
- d: in out darray) is
- begin
- destroy(d);
- d := new darray_info;
- determine_position(predict, 0, high_percent,
- d.first_idx, d.last_idx);
- d.first := first;
- d.high_percent := high_percent;
- d.expand_percent := expand_percent;
- d.arr := new array_type(1..predict);
- exception
- when out_of_bounds => -- determine_position fails
- destroy(d);
- raise;
- end create;
-
- procedure array_to_darray(a: in array_type;
- first: in integer:= 1;
- predict: in positive;
- high_percent: in positive
- := default_high;
- expand_percent: in positive
- := default_expand;
- d: in out darray) is
- begin
- free_array_ptr(d.arr);
- d := new darray_info;
- determine_position(predict, a'length, high_percent,
- d.first_idx, d.last_idx);
- d.first := first;
- d.high_percent := high_percent;
- d.expand_percent := expand_percent;
- d.arr := new array_type(1..predict);
- d.arr.all := a;
- exception
- when out_of_bounds => -- determine_position fails
- destroy(d);
- raise;
- end array_to_darray;
-
- procedure set_first(d: in out darray;
- first: in integer) is
- begin
- initialization_check(d);
- d.first := first;
- end set_first;
-
- procedure add_low(d: in out darray;
- e: in elem_type) is
- begin
- initialization_check(d);
- d.arr(d.first_idx - 1) := e;
- d.first_idx := d.first_idx - 1;
- d.first := d.first - 1;
- exception
- when constraint_error => -- on array store
- expand(d);
- d.arr(d.first_idx - 1) := e;
- d.first_idx := d.first_idx - 1;
- d.first := d.first - 1;
- end add_low;
-
- procedure add_high(d: in out darray;
- e: in elem_type) is
- begin
- initialization_check(d);
- d.arr(d.last_idx + 1) := e;
- d.last_idx := d.last_idx + 1;
- exception
- when constraint_error => -- on array store
- expand(d);
- d.arr(d.last_idx + 1) := e;
- d.last_idx := d.last_idx + 1;
- end add_high;
-
- procedure remove_low(d: in out darray) is
- begin
- initialization_check(d);
- if d.last_idx < d.first_idx then raise out_of_bounds; end if;
-
- d.first_idx := d.first_idx + 1;
- d.first := d.first + 1;
- contract(d);
- end remove_low;
-
- procedure remove_high(d: in out darray) is
- begin
- initialization_check(d);
- if d.last_idx < d.first_idx then raise out_of_bounds; end if;
-
- d.last_idx := d.last_idx - 1;
- contract(d);
- end remove_high;
-
- procedure store(d: in out darray;
- i: in integer;
- e: in elem_type) is
- begin
- initialization_check(d);
- d.arr(down_index(i, d)) := e;
- end store;
-
- function copy(d: darray)
- return darray is
- d2: darray;
- begin
- initialization_check(d);
- d2 := new darray_info'(first_idx => d.first_idx,
- last_idx => d.last_idx,
- first => d.first,
- high_percent => d.high_percent,
- expand_percent => d.expand_percent,
- arr => new array_type(1..d.arr'length));
- d2.arr.all := d.arr.all;
- return d2;
- end copy;
-
- function copy_deep(d: darray)
- return darray is
- d2: darray;
- begin
- initialization_check(d);
- d2 := new darray_info'(first_idx => d.first_idx,
- last_idx => d.last_idx,
- first => d.first,
- high_percent => d.high_percent,
- expand_percent => d.expand_percent,
- arr => new array_type(1..d.arr'length));
- for i in d.first_idx..d.last_idx loop
- d2.arr(i) := copy(d.arr(i));
- end loop;
- return d2;
- end copy_deep;
-
-
- -- Query Operations:
-
- function fetch(d: darray;
- i: integer)
- return elem_type is
- begin
- initialization_check(d);
- return d.arr(down_index(i, d));
- end fetch;
-
- function low(d: in darray)
- return elem_type is
- begin
- initialization_check(d);
- return d.arr(down_index(d.first, d));
- end low;
-
- function high(d: in darray)
- return elem_type is
- begin
- if is_empty(d) then -- is_empty checks for initialization
- raise out_of_bounds;
- end if;
- return d.arr(d.last_idx);
- end high;
-
- function first(d: in darray)
- return integer is
- begin
- initialization_check(d);
- return d.first;
- end first;
-
- function last(d: in darray)
- return integer is
- begin
- initialization_check(d);
- return d.first + d.last_idx - d.first_idx;
- end last;
-
- function is_empty(d: in darray)
- return boolean is
- begin
- initialization_check(d);
- return d.last_idx < d.first_idx;
- end is_empty;
-
- function length(d: in darray)
- return natural is
- begin
- initialization_check(d);
- return d.last_idx - d.first_idx + 1;
- end length;
-
- function equal(d1, d2: darray)
- return boolean is
- i2: integer;
- begin
- initialization_check(d1);
- initialization_check(d2);
-
- if d1.first /= d2.first or else length(d1) /= length(d2) then
- return false;
- end if;
-
- i2 := d2.first_idx;
- for i1 in d1.first_idx..d1.last_idx loop
- if not equal(d1.arr(i1), d2.arr(i2)) then
- return false;
- end if;
- i2 := i2 + 1;
- end loop;
-
- return true;
- end equal;
-
- function darray_to_array(d: darray)
- return array_type is
- subtype dbounds_array is array_type(d.first..last(d));
- -- invocation of last performs initialization check.
- begin
- return dbounds_array'(d.arr(d.first_idx..d.last_idx));
- end darray_to_array;
-
-
- -- Iterators:
-
- function make_elements_iter(d: darray)
- return elements_iter is
- begin
- initialization_check(d);
- return (current => d.first_idx,
- last => d.last_idx,
- arr => d.arr);
- end make_elements_iter;
-
- function more(iter: elements_iter)
- return boolean is
- begin
- return iter.current <= iter.last;
- end more;
-
- procedure next(iter: in out elements_iter;
- e: out elem_type) is
- begin
- if not more(iter) then raise no_more; end if;
-
- e := iter.arr(iter.current);
- iter.current := iter.current + 1;
- end next;
-
-
- -- Heap Management:
-
- procedure destroy(d: in out darray) is
- begin
- free_array_ptr(d.arr);
- free_darray(d);
- exception
- when constraint_error => -- d is null, d.arr is illegal.
- return;
- end destroy;
-
-
- -- Utilities:
-
- function down_index(i: integer;
- d: darray)
- return integer is
- down_idx: integer := i - d.first + d.first_idx;
- begin
- if d.last_idx < d.first_idx or else -- empty array
- not (down_idx in d.first_idx..d.last_idx) then -- bogus index
- raise out_of_bounds;
- end if;
-
- return down_idx;
- end down_index;
-
- procedure initialization_check(d: darray) is
- begin
- if d = null then raise uninitialized_darray; end if;
- end initialization_check;
-
- procedure expand(d: in out darray) is
- new_length: integer :=
- (d.arr'length * (100 + d.expand_percent))/100;
- begin
- -- Specified percent, in relation to length, may be too small to
- -- force any growth. In this case, force growth. This is rare.
- -- The choice to double is arbitrary.
-
- if new_length = d.arr'length then
- new_length := 2 * d.arr'length;
- end if;
-
- reallocate(d, new_length);
- end expand;
-
- procedure contract(d: in out darray) is
- -- <<A better contraction strategy is needed. Justification is weak
- -- for this one.>>
- begin
- null;
- end contract;
-
- procedure reallocate(d: in out darray;
- new_length: in positive) is
-
- new_arr: array_ptr;
- new_first_idx: integer;
- new_last_idx: integer;
-
- begin
- determine_position(new_length, length(d), d.high_percent,
- new_first_idx, new_last_idx);
- new_arr := new array_type(1..new_length);
- new_arr(new_first_idx..new_last_idx) :=
- d.arr(d.first_idx..d.last_idx);
- free_array_ptr(d.arr);
- d.arr := new_arr;
- d.first_idx := new_first_idx;
- d.last_idx := new_last_idx;
- end reallocate;
-
- procedure determine_position(array_length: in positive;
- slice_length: in natural;
- high_percent: in positive;
- first_idx: out positive;
- last_idx: out natural) is
-
- left_over: integer := array_length - slice_length;
- high_space: integer := (high_percent * left_over)/100;
- low_space: integer := left_over - high_space;
-
- begin
- if left_over < 0 then raise out_of_bounds; end if;
-
- first_idx := low_space + 1;
- last_idx := low_space + slice_length;
- end determine_position;
-
- end darray_pkg;
- --::::::::::
- --dlist.bdy
- --::::::::::
- package body DOUBLY_LINKED_LIST is
-
- --=======================================================================
- -- General-purpose routines
- --=======================================================================
- procedure ALLOCATE (ID : in out LIST_ID;
- ITEM : in ELEMENT_OBJECT;
- RESULT : out ELEMENT_POINTER) is
- NEW_ELEMENT : ELEMENT_POINTER;
- begin
- if ID.FREE = null then
- NEW_ELEMENT := new ELEMENT'(CONTENT => ITEM,
- NEXT => null,
- PREVIOUS => null);
- else
- NEW_ELEMENT := ID.FREE;
- ID.FREE := NEW_ELEMENT.NEXT;
- NEW_ELEMENT.CONTENT := ITEM;
- NEW_ELEMENT.NEXT := null;
- NEW_ELEMENT.PREVIOUS := null;
- end if;
- RESULT := NEW_ELEMENT;
- exception
- when others =>
- raise DYNAMIC_MEMORY_ALLOCATION_PROBLEM;
- end ALLOCATE;
-
- procedure ADD_TO_FREE (ID : in out LIST_ID;
- ITEM : in ELEMENT_POINTER) is
- begin
- if ID.FREE = null then
- ID.FREE := ITEM;
- ID.FREE.NEXT := null;
- else
- ITEM.NEXT := ID.FREE;
- ID.FREE := ITEM;
- end if;
- end ADD_TO_FREE;
-
- --=======================================================================
- -- Initialize
- --=======================================================================
- procedure INITIALIZE (ID : in out LIST_ID) is
-
- --=========================== PDL ==============================
- --|ABSTRACT:
- --| INITIALIZE initializes the list to empty. If the list
- --| contained any elements, they are prefixed to the free
- --| list.
- --|DESIGN DESCRIPTION:
- --| If the free list is empty (FREE is NULL)
- --| Set FREE to point to the first element (FIRST)
- --| Else
- --| If the current list is not empty (FIRST /= NULL)
- --| Set LAST.NEXT to point to the free list (FREE)
- --| Set FREE to point to the old list (FIRST)
- --| End if
- --| End if
- --| Set FIRST to NULL
- --| Set LAST to NULL
- --| Set CURRENT to NULL
- --| Set NUMBER_OF_ELEMENTS to 0
- --| Set CURRENT_INDEX to 0
- --==============================================================
-
- begin
- if ID.FREE = null then
- ID.FREE := ID.FIRST;
- else
- if ID.FIRST /= null then
- ID.LAST.NEXT := ID.FREE;
- ID.FREE := ID.FIRST;
- end if;
- end if;
- ID.FIRST := null;
- ID.LAST := null;
- ID.CURRENT := null;
- ID.NUMBER_OF_ELEMENTS := 0;
- ID.CURRENT_INDEX := 0;
- end INITIALIZE;
-
- --=======================================================================
- -- Return elements from the list
- --=======================================================================
- function FIRST_ELEMENT (ID : in LIST_ID) return ELEMENT_OBJECT is
-
- --=========================== PDL ==============================
- --|ABSTRACT:
- --| FIRST_ELEMENT returns the value (content) of the first
- --| element in the linked list.
- --|DESIGN DESCRIPTION:
- --| If the list is empty (IS_EMPTY), raise LIST_IS_EMPTY
- --| Return the first element of the list
- --==============================================================
-
- begin
- if IS_EMPTY (ID) then
- raise LIST_IS_EMPTY;
- end if;
- return ID.FIRST.CONTENT;
-
- exception
- when LIST_IS_EMPTY =>
- raise ;
- when others =>
- raise UNEXPECTED_ERROR;
- end FIRST_ELEMENT;
-
- function LAST_ELEMENT (ID : in LIST_ID) return ELEMENT_OBJECT is
-
- --=========================== PDL ==============================
- --|ABSTRACT:
- --| LAST_ELEMENT returns the value (content) of the last
- --| element in the linked list.
- --|DESIGN DESCRIPTION:
- --| If the list is empty (IS_EMPTY), raise LIST_IS_EMPTY
- --| Return the last element of the list
- --==============================================================
-
- begin
- if IS_EMPTY (ID) then
- raise LIST_IS_EMPTY;
- end if;
- return ID.LAST.CONTENT;
-
- exception
- when LIST_IS_EMPTY =>
- raise ;
- when others =>
- raise UNEXPECTED_ERROR;
- end LAST_ELEMENT;
-
- function CURRENT_ELEMENT (ID : in LIST_ID) return ELEMENT_OBJECT is
-
- --=========================== PDL ==============================
- --|ABSTRACT:
- --| CURRENT_ELEMENT returns the value (content) of the current
- --| element in the linked list.
- --|DESIGN DESCRIPTION:
- --| If the list is empty (IS_EMPTY), raise LIST_IS_EMPTY
- --| Return the current element of the list
- --==============================================================
-
- begin
- if IS_EMPTY (ID) then
- raise LIST_IS_EMPTY;
- end if;
- return ID.CURRENT.CONTENT;
-
- exception
- when LIST_IS_EMPTY =>
- raise ;
- when others =>
- raise UNEXPECTED_ERROR;
- end CURRENT_ELEMENT;
-
- --=======================================================================
- -- Position the current element in the list
- --=======================================================================
- procedure GOTO_FIRST (ID : in out LIST_ID) is
-
- --=========================== PDL ==============================
- --|ABSTRACT:
- --| GOTO_FIRST sets the current element to be the first
- --| element in the linked list.
- --|DESIGN DESCRIPTION:
- --| Set CURRENT to FIRST
- --==============================================================
-
- begin
- if IS_EMPTY (ID) then
- raise LIST_IS_EMPTY;
- end if;
- ID.CURRENT := ID.FIRST;
- ID.CURRENT_INDEX := 1;
-
- exception
- when LIST_IS_EMPTY =>
- raise ;
- when others =>
- raise UNEXPECTED_ERROR;
- end GOTO_FIRST;
-
- procedure GOTO_LAST (ID : in out LIST_ID) is
-
- --=========================== PDL ==============================
- --|ABSTRACT:
- --| GOTO_LAST sets the current element to be the last
- --| element in the linked list.
- --|DESIGN DESCRIPTION:
- --| Set CURRENT to LAST
- --==============================================================
-
- begin
- if IS_EMPTY (ID) then
- raise LIST_IS_EMPTY;
- end if;
- ID.CURRENT := ID.LAST;
- ID.CURRENT_INDEX := ID.NUMBER_OF_ELEMENTS;
-
- exception
- when LIST_IS_EMPTY =>
- raise ;
- when others =>
- raise UNEXPECTED_ERROR;
- end GOTO_LAST;
-
- procedure GOTO_ELEMENT (ID : in out LIST_ID;
- INDEX : in ELEMENT_POSITION) is
-
- --=========================== PDL ==============================
- --|ABSTRACT:
- --| GOTO sets the current element to be the Nth
- --| element in the linked list.
- --|DESIGN DESCRIPTION:
- --| If list IS_EMPTY, raise LIST_IS_EMPTY
- --| If INDEX > NUMBER_OF_ELEMENTS then raise INVALID_INDEX
- --| If INDEX < 1 then raise INVALID_INDEX
- --| Set CURRENT to point to the proper element
- --| Set CURRENT_INDEX to INDEX
- --==============================================================
-
- ROVER : ELEMENT_POINTER;
-
- begin
- if IS_EMPTY (ID) then
- raise LIST_IS_EMPTY;
- end if;
- if INDEX > ID.NUMBER_OF_ELEMENTS then
- raise INVALID_INDEX;
- end if;
- if INDEX < 1 then
- raise INVALID_INDEX;
- end if;
- ROVER := ID.FIRST;
- if INDEX > 1 then
- for I in 1 .. INDEX - 1 loop
- ROVER := ROVER.NEXT;
- end loop;
- end if;
- ID.CURRENT := ROVER;
- ID.CURRENT_INDEX := INDEX;
-
- exception
- when LIST_IS_EMPTY | INVALID_INDEX =>
- raise ;
- when others =>
- raise UNEXPECTED_ERROR;
- end GOTO_ELEMENT;
-
- --=======================================================================
- -- Return the indices of the current and last elements
- --=======================================================================
- function CURRENT_INDEX (ID : in LIST_ID) return ELEMENT_POSITION is
-
- --=========================== PDL ==============================
- --|ABSTRACT:
- --| CURRENT_INDEX returns the index number of the current
- --| element in the linked list.
- --|DESIGN DESCRIPTION:
- --| If list IS_EMPTY, raise LIST_IS_EMPTY
- --| Return CURRENT_INDEX
- --==============================================================
-
- begin
- if IS_EMPTY (ID) then
- raise LIST_IS_EMPTY;
- end if;
- return ID.CURRENT_INDEX;
-
- exception
- when LIST_IS_EMPTY =>
- raise ;
- when others =>
- raise UNEXPECTED_ERROR;
- end CURRENT_INDEX;
-
- function LAST_INDEX (ID : in LIST_ID) return ELEMENT_POSITION is
-
- --=========================== PDL ==============================
- --|ABSTRACT:
- --| LAST_INDEX returns the index number of the last
- --| element in the linked list.
- --|DESIGN DESCRIPTION:
- --| If list IS_EMPTY, raise LIST_IS_EMPTY
- --| Return NUMBER_OF_ELEMENTS
- --==============================================================
-
- begin
- if IS_EMPTY (ID) then
- raise LIST_IS_EMPTY;
- end if;
- return ID.NUMBER_OF_ELEMENTS;
-
- exception
- when LIST_IS_EMPTY =>
- raise ;
- when others =>
- raise UNEXPECTED_ERROR;
- end LAST_INDEX;
-
- --=======================================================================
- -- Move through the list
- --=======================================================================
- procedure ADVANCE (ID : in out LIST_ID) is
-
- --=========================== PDL ==============================
- --|ABSTRACT:
- --| ADVANCE sets the current element to be the next element
- --| if possible.
- --|DESIGN DESCRIPTION:
- --| If list IS_EMPTY, raise LIST_IS_EMPTY
- --| If at end of list (IS_END), raise ADVANCE_PAST_END_OF_LIST
- --| Set CURRENT.PREVIOUS to CURRENT
- --| Set CURRENT to CURRENT.NEXT
- --| Increment CURRENT_INDEX
- --|NOTE:
- --| ADVANCE will raise the ADVANCE_PAST_END_OF_LIST exception
- --| if we are already at the end of the list and try to
- --| advance from there. ADVANCE will not raise any exception
- --| if we were sitting on the last element and advanced to
- --| the end_of_list state. Hence, to use ADVANCE in coding,
- --| a recommended algorithm is:
- --| loop
- --| advance(mylist);
- --| exit when is_end(mylist);
- --| null; -- do what you wish with the next element
- --| end loop;
- --==============================================================
-
- begin
- if IS_EMPTY (ID) then
- raise LIST_IS_EMPTY;
- end if;
- if IS_END (ID) then
- raise ADVANCE_PAST_END_OF_LIST;
- end if;
- ID.CURRENT.PREVIOUS := ID.CURRENT;
- ID.CURRENT := ID.CURRENT.NEXT;
- ID.CURRENT_INDEX := ID.CURRENT_INDEX + 1;
-
- exception
- when LIST_IS_EMPTY | ADVANCE_PAST_END_OF_LIST =>
- raise ;
- when others =>
- raise UNEXPECTED_ERROR;
- end ADVANCE;
-
- procedure BACKUP (ID : in out LIST_ID) is
-
- --=========================== PDL ==============================
- --|ABSTRACT:
- --| BACKUP sets the current element to be the previous element
- --| if possible.
- --|DESIGN DESCRIPTION:
- --| If list IS_EMPTY, raise LIST_IS_EMPTY
- --| If at front of list (IS_FIRST), raise
- --| BACKUP_BEFORE_BEGINNING_OF_LIST
- --| Set CURRENT.PREVIOUS to CURRENT.PREVIOUS.PREVIOUS
- --| Set CURRENT.NEXT to CURRENT
- --| Set CURRENT to CURRENT.PREVIOUS
- --| Decrement CURRENT_INDEX
- --|NOTE:
- --| BACKUP will raise the BACKUP_BEFORE_BEGINNING_OF_LIST
- --| exception if we are already at the start of the list and try
- --| to backup from there. Hence, to use BACKUP in coding,
- --| a recommended algorithm is:
- --| loop
- --| null; -- do what you wish with the next element
- --| exit when is_first(mylist);
- --| backup(mylist);
- --| end loop;
- --==============================================================
-
- begin
- if IS_EMPTY (ID) then
- raise LIST_IS_EMPTY;
- end if;
- if IS_FIRST (ID) then
- raise BACKUP_BEFORE_BEGINNING_OF_LIST;
- end if;
- ID.CURRENT.PREVIOUS := ID.CURRENT.PREVIOUS.PREVIOUS;
- ID.CURRENT.NEXT := ID.CURRENT;
- ID.CURRENT := ID.CURRENT.PREVIOUS;
- ID.CURRENT_INDEX := ID.CURRENT_INDEX - 1;
-
- exception
- when LIST_IS_EMPTY | BACKUP_BEFORE_BEGINNING_OF_LIST =>
- raise ;
- when others =>
- raise UNEXPECTED_ERROR;
- end BACKUP;
-
- --=======================================================================
- -- Test the state of the list and the current element
- --=======================================================================
- function IS_EMPTY (ID : in LIST_ID) return BOOLEAN is
-
- --=========================== PDL ==============================
- --|ABSTRACT:
- --| IS_EMPTY returns TRUE if the list is empty; FALSE otherwise.
- --|DESIGN DESCRIPTION:
- --| If FIRST is NULL, return TRUE, else return FALSE
- --==============================================================
-
- begin
- return ID.FIRST = null;
- end IS_EMPTY;
-
- function IS_END (ID : in LIST_ID) return BOOLEAN is
-
- --=========================== PDL ==============================
- --|ABSTRACT:
- --| IS_END returns TRUE if we are past the last element of the
- --| list; FALSE otherwise.
- --|DESIGN DESCRIPTION:
- --| If CURRENT is NULL, return TRUE, else return FALSE
- --==============================================================
-
- begin
- return ID.CURRENT = null;
- end IS_END;
-
- function IS_FIRST (ID : in LIST_ID) return BOOLEAN is
-
- --=========================== PDL ==============================
- --|ABSTRACT:
- --| IS_FIRST returns TRUE if we are the first element of the
- --| list; FALSE otherwise.
- --|DESIGN DESCRIPTION:
- --| If CURRENT_INDEX is 1, return TRUE, else return FALSE
- --==============================================================
-
- begin
- return ID.CURRENT_INDEX = 1;
- end IS_FIRST;
-
- --=======================================================================
- -- Add elements to the list
- --=======================================================================
- procedure START_LIST (ID : in out LIST_ID;
- ELEMENT : ELEMENT_OBJECT) is
-
- --=========================== PDL ==============================
- --|ABSTRACT:
- --| START_LIST creates a new list with 1 element.
- --|DESIGN DESCRIPTION:
- --| Create NEW_ELEMENT (may raise DYNAMIC_MEMORY_ALLOCATION_PROBLEM)
- --| Set FIRST to NEW_ELEMENT
- --| Set LAST to NEW_ELEMENT
- --| Set CURRENT to NEW_ELEMENT
- --| Set NUMBER_OF_ELEMENTS to 1
- --| Set CURRENT_INDEX to 1
- --==============================================================
-
- NEW_ELEMENT : ELEMENT_POINTER;
- begin
- ALLOCATE (ID, ELEMENT, NEW_ELEMENT);
- ID.FIRST := NEW_ELEMENT;
- ID.LAST := NEW_ELEMENT;
- ID.CURRENT := NEW_ELEMENT;
- ID.NUMBER_OF_ELEMENTS := 1;
- ID.CURRENT_INDEX := 1;
- end START_LIST;
-
- procedure APPEND_ELEMENT (ID : in out LIST_ID;
- ELEMENT : ELEMENT_OBJECT) is
-
- --=========================== PDL ==============================
- --|ABSTRACT:
- --| APPEND_ELEMENT appends an element after the current
- --| element in the linked list. This new element is set
- --| to be the current element.
- --|DESIGN DESCRIPTION:
- --| If list IS_EMPTY
- --| Call START_LIST
- --| Else
- --| Create NEW_ELEMENT (may raise
- --| DYNAMIC_MEMORY_ALLOCATION_PROBLEM)
- --| If at end of list (CURRENT = LAST or IS_END)
- --| Set NEW_ELEMENT.PREVIOUS to LAST (NEW_ELEMENT.NEXT is
- --| already NULL)
- --| Set LAST.NEXT to NEW_ELEMENT
- --| Set LAST to NEW_ELEMENT
- --| Set CURRENT_INDEX to NUMBER_OF_ELEMENTS + 1
- --| Else
- --| Set NEW_ELEMENT.NEXT to CURRENT.NEXT
- --| Set NEW_ELEMENT.PREVIOUS to CURRENT
- --| Set CURRENT.NEXT.PREVIOUS to NEW_ELEMENT
- --| Set CURRENT.NEXT to NEW_ELEMENT
- --| Increment CURRENT_INDEX
- --| End if
- --| Set CURRENT to NEW_ELEMENT
- --| Increment NUMBER_OF_ELEMENTS
- --| End if
- --==============================================================
-
- NEW_ELEMENT : ELEMENT_POINTER;
- begin
- if IS_EMPTY (ID) then
- START_LIST (ID, ELEMENT);
- else
- ALLOCATE (ID, ELEMENT, NEW_ELEMENT);
- if ID.CURRENT = ID.LAST or IS_END (ID) then
- NEW_ELEMENT.PREVIOUS := ID.LAST;
- ID.LAST.NEXT := NEW_ELEMENT;
- ID.LAST := NEW_ELEMENT;
- ID.CURRENT_INDEX := ID.NUMBER_OF_ELEMENTS + 1;
- else
- NEW_ELEMENT.NEXT := ID.CURRENT.NEXT;
- NEW_ELEMENT.PREVIOUS := ID.CURRENT;
- ID.CURRENT.NEXT.PREVIOUS := NEW_ELEMENT;
- ID.CURRENT.NEXT := NEW_ELEMENT;
- ID.CURRENT_INDEX := ID.CURRENT_INDEX + 1;
- end if;
- ID.CURRENT := NEW_ELEMENT;
- ID.NUMBER_OF_ELEMENTS := ID.NUMBER_OF_ELEMENTS + 1;
- end if;
-
- exception
- when DYNAMIC_MEMORY_ALLOCATION_PROBLEM =>
- raise ;
- when others =>
- raise UNEXPECTED_ERROR;
- end APPEND_ELEMENT;
-
- procedure INSERT_ELEMENT (ID : in out LIST_ID;
- ELEMENT : ELEMENT_OBJECT) is
-
- --=========================== PDL ==============================
- --|ABSTRACT:
- --| INSERT_ELEMENT inserts an element before the current
- --| element in the linked list.
- --|DESIGN DESCRIPTION:
- --| If list IS_EMPTY
- --| Call START_LIST
- --| Else
- --| Create NEW_ELEMENT (may raise
- --| DYNAMIC_MEMORY_ALLOCATION_PROBLEM)
- --| If at front of list (IS_FIRST)
- --| Set NEW_ELEMENT.NEXT to FIRST
- --| Set FIRST.PREVIOUS to NEW_ELEMENT
- --| Set FIRST to NEW_ELEMENT
- --| ElsIf at end of list (IS_END)
- --| Set NEW_ELEMENT.PREVIOUS to LAST (NEW_ELEMENT.NEXT is
- --| already NULL)
- --| Set LAST.NEXT to NEW_ELEMENT
- --| Set LAST to NEW_ELEMENT
- --| Else
- --| Set NEW_ELEMENT.NEXT to CURRENT
- --| Set NEW_ELEMENT.PREVIOUS to CURRENT.PREVIOUS
- --| Set CURRENT.PREVIOUS.NEXT to NEW_ELEMENT
- --| Set CURRENT.PREVIOUS to NEW_ELEMENT
- --| End if
- --| Increment CURRENT_INDEX
- --| Increment NUMBER_OF_ELEMENTS
- --| End if
- --==============================================================
-
- NEW_ELEMENT : ELEMENT_POINTER;
- begin
- if IS_EMPTY (ID) then
- START_LIST (ID, ELEMENT);
- else
- ALLOCATE (ID, ELEMENT, NEW_ELEMENT);
- if IS_FIRST (ID) then
- NEW_ELEMENT.NEXT := ID.FIRST;
- ID.FIRST.PREVIOUS := NEW_ELEMENT;
- ID.FIRST := NEW_ELEMENT;
- elsif IS_END (ID) then
- NEW_ELEMENT.PREVIOUS := ID.LAST;
- ID.LAST.NEXT := NEW_ELEMENT;
- ID.LAST := NEW_ELEMENT;
- else
- NEW_ELEMENT.NEXT := ID.CURRENT;
- NEW_ELEMENT.PREVIOUS := ID.CURRENT.PREVIOUS;
- ID.CURRENT.PREVIOUS.NEXT := NEW_ELEMENT;
- ID.CURRENT.PREVIOUS := NEW_ELEMENT;
- end if;
- ID.CURRENT_INDEX := ID.CURRENT_INDEX + 1;
- ID.NUMBER_OF_ELEMENTS := ID.NUMBER_OF_ELEMENTS + 1;
- end if;
-
- exception
- when DYNAMIC_MEMORY_ALLOCATION_PROBLEM =>
- raise ;
- when others =>
- raise UNEXPECTED_ERROR;
- end INSERT_ELEMENT;
-
- --=======================================================================
- -- Delete elements from the list
- --=======================================================================
- procedure DELETE_ELEMENT (ID : in out LIST_ID) is
-
- --=========================== PDL ==============================
- --|ABSTRACT:
- --| DELETE_ELEMENT deletes the current element in the linked
- --| list. The next element is made the current element.
- --|DESIGN DESCRIPTION:
- --| If list IS_EMPTY raise LIST_IS_EMPTY
- --| If list IS_END raise ADVANCE_PAST_END_OF_LIST
- --| If CURRENT is FIRST
- --| Set FIRST to CURRENT.NEXT
- --| Else
- --| Set NEXT of CURRENT.PREVIOUS to CURRENT.NEXT
- --| End if
- --| If CURRENT is LAST
- --| Set LAST to CURRENT.PREVIOUS
- --| Free up CURRENT
- --| Set CURRENT to NULL
- --| Else
- --| Set PREVIOUS of CURRENT.NEXT to CURRENT.PREVIOUS
- --| Free up CURRENT
- --| Set CURRENT to CURRENT.NEXT
- --| End if
- --| Decrement NUMBER_OF_ELEMENTS
- --==============================================================
-
- SAVE : ELEMENT_POINTER;
-
- begin
- if IS_EMPTY (ID) then
- raise LIST_IS_EMPTY;
- end if;
- if IS_END (ID) then
- raise ADVANCE_PAST_END_OF_LIST;
- end if;
- if ID.CURRENT = ID.FIRST then
- ID.FIRST := ID.CURRENT.NEXT;
- else
- ID.CURRENT.PREVIOUS.NEXT := ID.CURRENT.NEXT;
- end if;
- if ID.CURRENT = ID.LAST then
- ID.LAST := ID.CURRENT.PREVIOUS;
- ADD_TO_FREE (ID, ID.CURRENT);
- ID.CURRENT := null;
- else
- ID.CURRENT.NEXT.PREVIOUS := ID.CURRENT.PREVIOUS;
- SAVE := ID.CURRENT.NEXT;
- ADD_TO_FREE (ID, ID.CURRENT);
- ID.CURRENT := SAVE;
- end if;
- ID.NUMBER_OF_ELEMENTS := ID.NUMBER_OF_ELEMENTS - 1;
-
- exception
- when LIST_IS_EMPTY | ADVANCE_PAST_END_OF_LIST =>
- raise ;
- when others =>
- raise UNEXPECTED_ERROR;
- end DELETE_ELEMENT;
-
- end DOUBLY_LINKED_LIST;
- --::::::::::
- --dyn.bdy
- --::::::::::
- package body DYN is
-
- procedure CLEAR(DSTR: in out DYN_STRING) is
-
- begin
- DSTR.SIZE := 0;
- end CLEAR;
-
- function D_STRING(CHAR: CHARACTER) return DYN_STRING is
-
- DS : DYN_STRING;
-
- begin
- DS.SIZE := 1;
- DS.DATA(1) := CHAR;
- return DS;
- end D_STRING;
-
- function D_STRING(STR : STRING ) return DYN_STRING is
-
- DS : DYN_STRING;
-
- begin
- DS.SIZE := STR'LENGTH;
- DS.DATA(1..DS.SIZE) := STR;
- return DS;
- end D_STRING;
-
- function CHAR(DSTR : DYN_STRING;
- POSIT : POSITIVE := 1) return CHARACTER is
-
- begin
- if POSIT > DSTR.SIZE then
- raise STRING_TOO_SHORT;
- else
- return DSTR.DATA(POSIT);
- end if;
- end CHAR;
-
- function STR (DSTR: DYN_STRING) return STRING is
-
- begin
- return DSTR.DATA(1..DSTR.SIZE);
- end STR;
-
- function LENGTH(DSTR: DYN_STRING) return NATURAL is
-
- begin
- return DSTR.SIZE;
- end LENGTH;
-
- begin --(DYN)
- null;
- exception
- when others =>
- raise;
-
- end DYN;
-